diff --git a/CHANGELOG.md b/CHANGELOG.md
index e649659..fd0bb5a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,12 +11,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
+
### Removed
### Security
### Fixed
+## [0.3.2-pre]
+
+### Added
+
+- [Files] Files can now be selected multiple files and downloaded, deleted, moved, etc.
+- [Apps] Support to modify the application opening address.([#204](https://github.com/IceWhaleTech/CasaOS/issues/204))
+
+### Changed
+
+- [Apps] Hide the display of non-essential environment variables in the application.
+- [System] Network, disk, cpu, memory, etc. information is modified to be pushed via socket.
+- [System] Optimize opening speed.([#214](https://github.com/IceWhaleTech/CasaOS/issues/214))
+### Fixed
+
+- [System] Fixed the problem that sync data cannot submit the device ID ([#68](https://github.com/IceWhaleTech/CasaOS/issues/68))
+- [Files] Fixed the code editor center alignment display problem.([#210](https://github.com/IceWhaleTech/CasaOS/issues/210))
+- [Files] Fixed the problem of wrong name when downloading files.([#240](https://github.com/IceWhaleTech/CasaOS/issues/240))
+- [System] Fixed the network display as a negative number problem.([#224](https://github.com/IceWhaleTech/CasaOS/issues/224))
+
## [0.3.1.1] - 2022-05-17
### Fixed
diff --git a/go.mod b/go.mod
index 5f58773..dafddeb 100644
--- a/go.mod
+++ b/go.mod
@@ -7,6 +7,9 @@ require (
github.com/Microsoft/go-winio v0.5.0 // indirect
github.com/Microsoft/hcsshim v0.8.22 // indirect
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect
+ github.com/ambelovsky/go-structs v1.1.0 // indirect
+ github.com/ambelovsky/gosf v0.0.0-20201109201340-237aea4d6109
+ github.com/ambelovsky/gosf-socketio v0.0.0-20201109193639-add9d32f8b19 // indirect
github.com/bits-and-blooms/bitset v1.2.1 // indirect
github.com/containerd/containerd v1.5.7
github.com/containerd/continuity v0.2.0 // indirect
@@ -29,6 +32,7 @@ require (
github.com/gomodule/redigo v1.8.5
github.com/google/go-github/v36 v36.0.0
github.com/google/uuid v1.3.0 // indirect
+ github.com/googollee/go-socket.io v1.6.2
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/websocket v1.4.2
github.com/jinzhu/copier v0.3.2
@@ -39,6 +43,7 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-sqlite3 v1.14.11 // indirect
+ github.com/mholt/archiver/v3 v3.5.1
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect
@@ -53,7 +58,6 @@ require (
github.com/sirupsen/logrus v1.8.1
github.com/smartystreets/assertions v1.2.0 // indirect
github.com/smartystreets/goconvey v1.6.4 // indirect
- github.com/spf13/afero v1.2.2
github.com/swaggo/gin-swagger v1.3.0
github.com/swaggo/swag v1.7.3
github.com/tidwall/gjson v1.10.2
diff --git a/go.sum b/go.sum
index ba51340..39ab4b4 100644
--- a/go.sum
+++ b/go.sum
@@ -99,6 +99,14 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
+github.com/ambelovsky/go-structs v1.1.0 h1:LXj4/mHnYw0qhXQhOo96+ULGQ88H8qMcZd5SHef8boY=
+github.com/ambelovsky/go-structs v1.1.0/go.mod h1:zN3RBXQvxgjjq/Q/WZS7p5AEK+qC9mNg7ycnvoQ63Ak=
+github.com/ambelovsky/gosf v0.0.0-20201109201340-237aea4d6109 h1:Tp8GVfUOEmJftBqi4+/aXTwJzm24POo6wIHeuTqaT+Y=
+github.com/ambelovsky/gosf v0.0.0-20201109201340-237aea4d6109/go.mod h1:MUREokfMKREm1fOm2babarrkYdk/dGHWY+ITC3qHHPQ=
+github.com/ambelovsky/gosf-socketio v0.0.0-20201109193639-add9d32f8b19 h1:suVCm9PiIhz7ftTbWQNe7u2YjVfr8AEuUiNWKWApdMM=
+github.com/ambelovsky/gosf-socketio v0.0.0-20201109193639-add9d32f8b19/go.mod h1:o0+8DH+3X+FEOgSdNud0+8jJAsjtR9H3hF+O10Zcj/c=
+github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSULpEc=
+github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
@@ -289,6 +297,9 @@ github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
+github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
+github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
+github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
github.com/dsoprea/go-exif/v2 v2.0.0-20200321225314-640175a69fe4/go.mod h1:Lm2lMM2zx8p4a34ZemkaUV95AnMl4ZvLbCUbwOvLC2E=
github.com/dsoprea/go-exif/v3 v3.0.0-20200717053412-08f1b6708903/go.mod h1:0nsO1ce0mh5czxGeLo4+OCZ/C6Eo6ZlMWsz7rH/Gxv8=
github.com/dsoprea/go-exif/v3 v3.0.0-20210625224831-a6301f85c82b h1:NgNuLvW/gAFKU30ULWW0gtkCt56JfB7FrZ2zyo0wT8I=
@@ -401,6 +412,7 @@ github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblf
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
@@ -453,6 +465,9 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw=
+github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/gomodule/redigo v1.8.4/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
github.com/gomodule/redigo v1.8.5 h1:nRAxCa+SVsyjSBrtZmG/cqb6VbTmuRzpg/PoTFlpumc=
github.com/gomodule/redigo v1.8.5/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@@ -499,6 +514,8 @@ github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE0
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
+github.com/googollee/go-socket.io v1.6.2 h1:olKLLHJtHz1IkL/OrTyNriZZvVQYEORNkJAqsOwPask=
+github.com/googollee/go-socket.io v1.6.2/go.mod h1:0vGP8/dXR9SZUMMD4+xxaGo/lohOw3YWMh2WRiWeKxg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
@@ -563,10 +580,15 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
+github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
+github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -619,10 +641,13 @@ github.com/mattn/go-sqlite3 v1.14.11 h1:gt+cp9c0XGqe9S/wAHTL3n/7MqY+siPWgWJgqdsF
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.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
+github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo=
+github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
@@ -651,6 +676,8 @@ github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
+github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
@@ -711,6 +738,8 @@ github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTK
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
+github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM=
+github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -813,7 +842,6 @@ github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:Udh
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
-github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
@@ -875,6 +903,9 @@ github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLY
github.com/ugorji/go/codec v1.1.13/go.mod h1:oNVt3Dq+FO91WNQ/9JnHKQP2QJxTzoN7wCBFCq1OeuU=
github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
+github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
+github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I=
+github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
@@ -893,6 +924,8 @@ github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
+github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
+github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/main.go b/main.go
index dd32fa6..ca29a75 100644
--- a/main.go
+++ b/main.go
@@ -4,16 +4,18 @@ import (
"flag"
"fmt"
"net/http"
+ "strconv"
"time"
+ "github.com/IceWhaleTech/CasaOS/model"
+ "github.com/IceWhaleTech/CasaOS/model/notify"
"github.com/IceWhaleTech/CasaOS/pkg/cache"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/sqlite"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
+ "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
"github.com/IceWhaleTech/CasaOS/route"
"github.com/IceWhaleTech/CasaOS/service"
- model2 "github.com/IceWhaleTech/CasaOS/service/model"
- "github.com/IceWhaleTech/CasaOS/types"
"github.com/robfig/cron"
"gorm.io/gorm"
@@ -46,6 +48,7 @@ func init() {
service.CancelList = make(map[string]string)
service.InternalInspection = make(map[string][]string)
service.NewVersionApp = make(map[string]string)
+ service.FileQueue = make(map[string]model.FileOperate)
route.InitFunction()
go service.SendIPToServer()
@@ -66,12 +69,24 @@ func init() {
// @name Authorization
// @BasePath /v1
func main() {
+
+ service.NotifyMsg = make(chan notify.Message, 10)
if *showUserInfo {
fmt.Println("CasaOS User Info")
fmt.Println("UserName:" + config.UserInfo.UserName)
fmt.Println("Password:" + config.UserInfo.PWD)
return
}
+ p, _ := port.GetAvailablePort("tcp")
+ config.ServerInfo.SocketPort = strconv.Itoa(p)
+ go route.ScoketInit(p, service.NotifyMsg)
+ go func() {
+ for i := 0; i < 1000; i++ {
+ time.Sleep(2 * time.Second)
+ //service.NotifyMsg <- strconv.Itoa(i)
+ }
+ }()
+
//model.Setup()
//gredis.Setup()
r := route.InitRouter()
@@ -86,18 +101,19 @@ func main() {
service.SendIPToServer()
service.LoopFriend()
- service.MyService.App().CheckNewImage()
+ //service.MyService.App().CheckNewImage()
})
if err != nil {
fmt.Println(err)
}
- err = cron2.AddFunc("0/1 * * * * *", func() {
- notify := model2.AppNotify{}
- notify.CustomId = ""
- notify.Type = types.NOTIFY_TYPE_HEALTH_CHECK
-
- go service.MyService.Notify().SendText(notify)
-
+ err = cron2.AddFunc("0/3 * * * * *", func() {
+ if service.ClientCount > 0 {
+ route.SendNetINfoBySocket()
+ route.SendCPUBySocket()
+ route.SendMemBySocket()
+ route.SendDiskBySocket()
+ route.SendUSBBySocket()
+ }
})
if err != nil {
fmt.Println(err)
@@ -114,4 +130,7 @@ func main() {
s.ListenAndServe()
+ // if err := r.Run(fmt.Sprintf(":%v", config.ServerInfo.HttpPort)); err != nil {
+ // fmt.Println("failed run app: ", err)
+ // }
}
diff --git a/middleware/gin.go b/middleware/gin.go
index e3d21f8..c3647c1 100644
--- a/middleware/gin.go
+++ b/middleware/gin.go
@@ -1,3 +1,13 @@
+/*
+ * @Author: LinkLeong link@icewhale.com
+ * @Date: 2021-10-08 10:29:08
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-05-25 19:17:45
+ * @FilePath: /CasaOS/middleware/gin.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
package middleware
import (
@@ -10,20 +20,16 @@ import (
func Cors() gin.HandlerFunc {
return func(c *gin.Context) {
method := c.Request.Method
- //origin := c.Request.Header.Get("Origin") //请求头部
- //if origin != "" {
- //接收客户端发送的origin (重要!)
- c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
+
c.Header("Access-Control-Allow-Origin", "*")
- //服务器支持的所有跨域请求的方法
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
//允许跨域设置可以返回其他子段,可以自定义字段
c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,Language")
// 允许浏览器(客户端)可以解析的头部 (重要)
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers")
+ //c.Writer.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type, Content-Length, X-CSRF-Token, Token, session, Origin, Host, Connection, Accept-Encoding, Accept-Language, X-Requested-With")
//设置缓存时间
c.Header("Access-Control-Max-Age", "172800")
- //允许客户端传递校验信息比如 cookie (重要)
c.Header("Access-Control-Allow-Credentials", "true")
c.Set("content-type", "application/json")
//}
diff --git a/model/file.go b/model/file.go
new file mode 100644
index 0000000..5c012df
--- /dev/null
+++ b/model/file.go
@@ -0,0 +1,31 @@
+/*
+ * @Author: LinkLeong link@icewhale.com
+ * @Date: 2022-05-20 16:27:12
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-05-30 18:24:42
+ * @FilePath: /CasaOS/model/file.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+package model
+
+type FileOperate struct {
+ Type string `json:"type" binding:"required"`
+ Item []FileItem `json:"item" binding:"required"`
+ TotalSize int64 `json:"total_size"`
+ ProcessedSize int64 `json:"processed_size"`
+ To string `json:"to" binding:"required"`
+}
+
+type FileItem struct {
+ From string `json:"from" binding:"required"`
+ Finished bool `json:"finished"`
+ Size int64 `json:"size"`
+ ProcessedSize int64 `json:"processed_size"`
+}
+
+type FileUpdate struct {
+ FilePath string `json:"path" binding:"required"`
+ FileContent string `json:"content" binding:"required"`
+}
diff --git a/model/manifest.go b/model/manifest.go
index 8254205..541c4a4 100644
--- a/model/manifest.go
+++ b/model/manifest.go
@@ -127,4 +127,6 @@ type CustomizationPostData struct {
Privileged bool `json:"privileged"`
CapAdd []string `json:"cap_add"`
Cmd []string `json:"cmd"`
+ Protocol string `json:"protocol"`
+ Host string `json:"host"`
}
diff --git a/model/notify/application.go b/model/notify/application.go
new file mode 100644
index 0000000..439de9f
--- /dev/null
+++ b/model/notify/application.go
@@ -0,0 +1,21 @@
+/*
+ * @Author: LinkLeong link@icewhale.com
+ * @Date: 2022-05-27 15:01:58
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-05-31 14:51:21
+ * @FilePath: /CasaOS/model/notify/application.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+package notify
+
+type Application struct {
+ Name string `json:"name"`
+ State string `json:"state"`
+ Type string `json:"type"`
+ Icon string `json:"icon"`
+ Message string `json:"message"`
+ Finished bool `json:"finished"`
+ Success bool `json:"success"`
+}
diff --git a/model/notify/file.go b/model/notify/file.go
new file mode 100644
index 0000000..8192dca
--- /dev/null
+++ b/model/notify/file.go
@@ -0,0 +1,21 @@
+/*
+ * @Author: LinkLeong link@icewhale.com
+ * @Date: 2022-05-26 14:21:57
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-05-30 18:51:36
+ * @FilePath: /CasaOS/model/notify/file.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+package notify
+
+type File struct {
+ Finished bool `json:"finished"`
+ ProcessedSize int64 `json:"processed_size"`
+ ProcessingPath string `json:"processing_path"`
+ Status string `json:"status"`
+ TotalSize int64 `json:"total_size"`
+ Id string `json:"id"`
+ To string `json:"to"`
+}
diff --git a/model/notify/message.go b/model/notify/message.go
new file mode 100644
index 0000000..904b9a2
--- /dev/null
+++ b/model/notify/message.go
@@ -0,0 +1,20 @@
+/*
+ * @Author: LinkLeong link@icewhale.com
+ * @Date: 2022-05-26 14:39:22
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-05-26 19:08:52
+ * @FilePath: /CasaOS/model/notify/message.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+package notify
+
+import (
+ f "github.com/ambelovsky/gosf"
+)
+
+type Message struct {
+ Path string `json:"path"`
+ Msg f.Message `json:"msg"`
+}
diff --git a/model/notify/person.go b/model/notify/person.go
new file mode 100644
index 0000000..a2b903b
--- /dev/null
+++ b/model/notify/person.go
@@ -0,0 +1,16 @@
+/*
+ * @Author: LinkLeong link@icewhale.com
+ * @Date: 2022-05-27 18:42:42
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-05-27 18:43:08
+ * @FilePath: /CasaOS/model/notify/person.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+package notify
+
+type Person struct {
+ ShareId string `json:"share_id"`
+ Type string `json:"type"`
+}
diff --git a/model/notify/result.go b/model/notify/result.go
new file mode 100644
index 0000000..9edb6f9
--- /dev/null
+++ b/model/notify/result.go
@@ -0,0 +1,18 @@
+/*
+ * @Author: LinkLeong link@icewhale.com
+ * @Date: 2022-05-26 14:21:11
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-05-27 11:15:59
+ * @FilePath: /CasaOS/model/notify/result.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+
+package notify
+
+// Notify struct for Notify
+type NotifyModel struct {
+ Data interface{} `json:"data"`
+ State string `json:"state"`
+}
diff --git a/model/sys_common.go b/model/sys_common.go
index 6fd86ea..980f784 100644
--- a/model/sys_common.go
+++ b/model/sys_common.go
@@ -1,3 +1,13 @@
+/*
+ * @Author: LinkLeong link@icewhale.com
+ * @Date: 2022-05-13 18:15:46
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-05-30 16:43:59
+ * @FilePath: /CasaOS/model/sys_common.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
package model
import "time"
@@ -31,6 +41,7 @@ type ServerModel struct {
Token string
UDPPort string
USBAutoMount string
+ SocketPort string
}
//服务配置
diff --git a/pkg/utils/file/file.go b/pkg/utils/file/file.go
index 6c8b2ac..ea8eeb8 100644
--- a/pkg/utils/file/file.go
+++ b/pkg/utils/file/file.go
@@ -2,9 +2,11 @@ package file
import (
"bufio"
+ "errors"
"fmt"
"io"
"io/ioutil"
+ "log"
"mime/multipart"
"os"
"path"
@@ -12,6 +14,8 @@ import (
"path/filepath"
"strconv"
"strings"
+
+ "github.com/mholt/archiver/v3"
)
// GetSize get the file size
@@ -332,3 +336,149 @@ func SpliceFiles(dir, path string, length int, startPoint int) error {
return nil
}
+
+func GetCompressionAlgorithm(t string) (string, archiver.Writer, error) {
+
+ switch t {
+ case "zip", "":
+ return ".zip", archiver.NewZip(), nil
+ case "tar":
+ return ".tar", archiver.NewTar(), nil
+ case "targz":
+ return ".tar.gz", archiver.NewTarGz(), nil
+ case "tarbz2":
+ return ".tar.bz2", archiver.NewTarBz2(), nil
+ case "tarxz":
+ return ".tar.xz", archiver.NewTarXz(), nil
+ case "tarlz4":
+ return ".tar.lz4", archiver.NewTarLz4(), nil
+ case "tarsz":
+ return ".tar.sz", archiver.NewTarSz(), nil
+ default:
+ return "", nil, errors.New("format not implemented")
+ }
+}
+func AddFile(ar archiver.Writer, path, commonPath string) error {
+
+ info, err := os.Stat(path)
+ if err != nil {
+ return err
+ }
+
+ if !info.IsDir() && !info.Mode().IsRegular() {
+ return nil
+ }
+
+ file, err := os.Open(path)
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+
+ if path != commonPath {
+ filename := info.Name()
+ err = ar.Write(archiver.File{
+ FileInfo: archiver.FileInfo{
+ FileInfo: info,
+ CustomName: filename,
+ },
+ ReadCloser: file,
+ })
+ if err != nil {
+ return err
+ }
+ }
+
+ if info.IsDir() {
+ names, err := file.Readdirnames(0)
+ if err != nil {
+ return err
+ }
+
+ for _, name := range names {
+ err = AddFile(ar, filepath.Join(path, name), commonPath)
+ if err != nil {
+ log.Printf("Failed to archive %v", err)
+ }
+ }
+ }
+
+ return nil
+}
+func CommonPrefix(sep byte, paths ...string) string {
+ // Handle special cases.
+ switch len(paths) {
+ case 0:
+ return ""
+ case 1:
+ return path.Clean(paths[0])
+ }
+
+ // Note, we treat string as []byte, not []rune as is often
+ // done in Go. (And sep as byte, not rune). This is because
+ // most/all supported OS' treat paths as string of non-zero
+ // bytes. A filename may be displayed as a sequence of Unicode
+ // runes (typically encoded as UTF-8) but paths are
+ // not required to be valid UTF-8 or in any normalized form
+ // (e.g. "é" (U+00C9) and "é" (U+0065,U+0301) are different
+ // file names.
+ c := []byte(path.Clean(paths[0]))
+
+ // We add a trailing sep to handle the case where the
+ // common prefix directory is included in the path list
+ // (e.g. /home/user1, /home/user1/foo, /home/user1/bar).
+ // path.Clean will have cleaned off trailing / separators with
+ // the exception of the root directory, "/" (in which case we
+ // make it "//", but this will get fixed up to "/" bellow).
+ c = append(c, sep)
+
+ // Ignore the first path since it's already in c
+ for _, v := range paths[1:] {
+ // Clean up each path before testing it
+ v = path.Clean(v) + string(sep)
+
+ // Find the first non-common byte and truncate c
+ if len(v) < len(c) {
+ c = c[:len(v)]
+ }
+ for i := 0; i < len(c); i++ {
+ if v[i] != c[i] {
+ c = c[:i]
+ break
+ }
+ }
+ }
+
+ // Remove trailing non-separator characters and the final separator
+ for i := len(c) - 1; i >= 0; i-- {
+ if c[i] == sep {
+ c = c[:i]
+ break
+ }
+ }
+
+ return string(c)
+}
+
+func GetFileOrDirSize(path string) (int64, error) {
+ fileInfo, err := os.Stat(path)
+ if err != nil {
+ return 0, err
+ }
+ if fileInfo.IsDir() {
+ return DirSizeB(path + "/")
+ }
+ return fileInfo.Size(), nil
+}
+
+//getFileSize get file size by path(B)
+func DirSizeB(path string) (int64, error) {
+ var size int64
+ err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
+ if !info.IsDir() {
+ size += info.Size()
+ }
+ return err
+ })
+ return size, err
+}
diff --git a/route/init.go b/route/init.go
index 9481ce5..14ab707 100644
--- a/route/init.go
+++ b/route/init.go
@@ -3,6 +3,7 @@ package route
import (
"encoding/xml"
"fmt"
+ "path/filepath"
"runtime"
"strconv"
"strings"
@@ -79,14 +80,12 @@ func installSyncthing(appId string) {
appInfo.Tip = env_helper.ReplaceStringDefaultENV(appInfo.Tip)
}
- appInfo.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20
+ appInfo.MaxMemory = service.MyService.System().GetMemInfo().Total >> 20
id := uuid.NewV4().String()
- installLog := model2.AppNotify{}
-
// step:下载镜像
- err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, installLog)
+ err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, "", "")
if err != nil {
//pull image error
fmt.Println("pull image error", err, dockerImage, dockerImageVersion)
@@ -142,14 +141,13 @@ func checkSystemApp() {
}
path := ""
- for _, i := range info.HostConfig.Mounts {
- if i.Target == "/config" {
+ for _, i := range info.Mounts {
+ if i.Destination == "/config" {
path = i.Source
-
break
}
}
- content := file.ReadFullFile(path + "config.xml")
+ content := file.ReadFullFile(filepath.Join(path, "config.xml"))
syncConfig := &system_app.SyncConfig{}
xml.Unmarshal(content, &syncConfig)
config.SystemConfigInfo.SyncKey = syncConfig.Key
diff --git a/route/periodical.go b/route/periodical.go
new file mode 100644
index 0000000..a6554d0
--- /dev/null
+++ b/route/periodical.go
@@ -0,0 +1,155 @@
+/*
+ * @Author: LinkLeong link@icewhale.com
+ * @Date: 2022-05-27 15:55:36
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-05-27 18:57:40
+ * @FilePath: /CasaOS/route/periodical.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+package route
+
+import (
+ "reflect"
+ "strconv"
+ "strings"
+ "time"
+ "unsafe"
+
+ "github.com/IceWhaleTech/CasaOS/model"
+ "github.com/IceWhaleTech/CasaOS/service"
+)
+
+func SendNetINfoBySocket() {
+ netList := service.MyService.System().GetNetInfo()
+ newNet := []model.IOCountersStat{}
+ nets := service.MyService.System().GetNet(true)
+ for _, n := range netList {
+ for _, netCardName := range nets {
+ if n.Name == netCardName {
+ item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
+ item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name))
+ item.Time = time.Now().Unix()
+ newNet = append(newNet, item)
+ break
+ }
+ }
+ }
+ service.MyService.Notify().SendNetInfoBySocket(newNet)
+}
+
+func SendCPUBySocket() {
+ cpu := service.MyService.System().GetCpuPercent()
+ num := service.MyService.System().GetCpuCoreNum()
+ cpuData := make(map[string]interface{})
+ cpuData["percent"] = cpu
+ cpuData["num"] = num
+ service.MyService.Notify().SendCPUInfoBySocket(cpuData)
+}
+
+func SendMemBySocket() {
+ service.MyService.Notify().SendMemInfoBySocket(service.MyService.System().GetMemInfo())
+}
+
+func SendDiskBySocket() {
+ list := service.MyService.Disk().LSBLK(true)
+
+ summary := model.Summary{}
+ healthy := true
+ findSystem := 0
+
+ for i := 0; i < len(list); i++ {
+ if len(list[i].Children) > 0 && findSystem == 0 {
+
+ for j := 0; j < len(list[i].Children); j++ {
+
+ if len(list[i].Children[j].Children) > 0 {
+ for _, v := range list[i].Children[j].Children {
+ if v.MountPoint == "/" {
+ s, _ := strconv.ParseUint(v.FSSize, 10, 64)
+ a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
+ u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
+ summary.Size += s
+ summary.Avail += a
+ summary.Used += u
+ findSystem = 1
+ break
+ }
+ }
+ } else {
+ if list[i].Children[j].MountPoint == "/" {
+ s, _ := strconv.ParseUint(list[i].Children[j].FSSize, 10, 64)
+ a, _ := strconv.ParseUint(list[i].Children[j].FSAvail, 10, 64)
+ u, _ := strconv.ParseUint(list[i].Children[j].FSUsed, 10, 64)
+ summary.Size += s
+ summary.Avail += a
+ summary.Used += u
+ findSystem = 1
+ break
+ }
+ }
+ }
+
+ }
+ if findSystem == 1 {
+ findSystem += 1
+ continue
+ }
+ if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" {
+ temp := service.MyService.Disk().SmartCTL(list[i].Path)
+ if reflect.DeepEqual(temp, model.SmartctlA{}) {
+ continue
+ }
+
+ //list[i].Temperature = temp.Temperature.Current
+ if !temp.SmartStatus.Passed {
+ healthy = false
+ }
+ if len(list[i].Children) > 0 {
+ for _, v := range list[i].Children {
+ s, _ := strconv.ParseUint(v.FSSize, 10, 64)
+ a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
+ u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
+ summary.Size += s
+ summary.Avail += a
+ summary.Used += u
+ }
+ }
+
+ }
+ }
+
+ summary.Health = healthy
+ service.MyService.Notify().SendDiskInfoBySocket(summary)
+}
+
+func SendUSBBySocket() {
+ 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)
+ }
+ }
+ service.MyService.Notify().SendUSBInfoBySocket(usb)
+}
diff --git a/route/route.go b/route/route.go
index f2b8459..e651417 100644
--- a/route/route.go
+++ b/route/route.go
@@ -31,7 +31,6 @@ func InitRouter() *gin.Engine {
if swagHandler != nil {
r.GET("/swagger/*any", swagHandler)
}
-
r.POST("/v1/user/login", v1.Login)
r.GET("/v1/guide/check", v1.GetGuideCheck)
@@ -43,6 +42,7 @@ func InitRouter() *gin.Engine {
r.GET("/v1/user/info", v1.GetUserInfo)
//get user info
r.GET("/v1/person/shareid", v1.GetPersonShareId)
+ r.GET("/v1/sys/socket/port", v1.GetSystemSocketPort)
v1Group := r.Group("/v1")
v1Group.Use(jwt2.JWT(swagHandler))
@@ -127,7 +127,7 @@ func InitRouter() *gin.Engine {
//暂停或启动容器
v1AppGroup.PUT("/state/:id", v1.ChangAppState)
//安装app
- v1AppGroup.POST("/install/:id", v1.InstallApp)
+ v1AppGroup.POST("/install", v1.InstallApp)
//卸载app
v1AppGroup.DELETE("/uninstall/:id", v1.UnInstallApp)
//获取安装进度
@@ -164,6 +164,7 @@ func InitRouter() *gin.Engine {
v1SysGroup.PUT("/usb/off", v1.PutSystemOffUSBAutoMount)
v1SysGroup.PUT("/usb/on", v1.PutSystemOnUSBAutoMount)
v1SysGroup.GET("/usb", v1.GetSystemUSBAutoMount)
+
}
v1FileGroup := v1Group.Group("/file")
v1FileGroup.Use()
@@ -178,7 +179,7 @@ func InitRouter() *gin.Engine {
v1FileGroup.POST("/create", v1.PostCreateFile)
v1FileGroup.GET("/download", v1.GetDownloadFile)
- v1FileGroup.GET("/new/download", v1.GetFileDownloadNew)
+ v1FileGroup.GET("/download/*path", v1.GetDownloadSingleFile)
v1FileGroup.POST("/operate", v1.PostOperateFileOrDir)
v1FileGroup.DELETE("/delete", v1.DeleteFile)
v1FileGroup.PUT("/update", v1.PutFileContent)
@@ -235,12 +236,12 @@ func InitRouter() *gin.Engine {
}
- v1NotifyGroup := v1Group.Group("/notify")
- v1NotifyGroup.Use()
- {
- v1NotifyGroup.GET("/ws", v1.NotifyWS)
- v1NotifyGroup.PUT("/read/:id", v1.PutNotifyRead)
- }
+ // v1NotifyGroup := v1Group.Group("/notify")
+ // v1NotifyGroup.Use()
+ // {
+ // v1NotifyGroup.GET("/ws", v1.NotifyWS)
+ // v1NotifyGroup.PUT("/read/:id", v1.PutNotifyRead)
+ // }
v1PersonGroup := v1Group.Group("/person")
v1PersonGroup.Use()
diff --git a/route/socket.go b/route/socket.go
new file mode 100644
index 0000000..e74cd39
--- /dev/null
+++ b/route/socket.go
@@ -0,0 +1,39 @@
+/*
+ * @Author: LinkLeong link@icewhale.com
+ * @Date: 2022-05-23 17:18:56
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-05-30 17:06:08
+ * @FilePath: /CasaOS/route/socket.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+package route
+
+import (
+ "time"
+
+ "github.com/IceWhaleTech/CasaOS/model/notify"
+ "github.com/IceWhaleTech/CasaOS/service"
+ f "github.com/ambelovsky/gosf"
+)
+
+func ScoketInit(port int, msg chan notify.Message) {
+ f.OnConnect(func(c *f.Client, request *f.Request) {
+ service.ClientCount += 1
+ })
+ f.OnDisconnect(func(c *f.Client, request *f.Request) {
+ service.ClientCount -= 1
+ })
+ go func(msg chan notify.Message) {
+ for v := range msg {
+ f.Broadcast("", v.Path, &v.Msg)
+ time.Sleep(time.Millisecond * 300)
+ }
+
+ }(msg)
+
+ f.Startup(map[string]interface{}{
+ "port": port})
+
+}
diff --git a/route/v1/app.go b/route/v1/app.go
index 2104eb5..75805ef 100644
--- a/route/v1/app.go
+++ b/route/v1/app.go
@@ -209,7 +209,7 @@ func AppInfo(c *gin.Context) {
// sort.VolSort(volOrder).Sort(info.Volumes.([]model.PathMap))
// sort.DevSort(devOrder).Sort(info.Devices)
- info.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20
+ info.MaxMemory = service.MyService.System().GetMemInfo().Total >> 20
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
}
diff --git a/route/v1/docker.go b/route/v1/docker.go
index 14341c6..298ac55 100644
--- a/route/v1/docker.go
+++ b/route/v1/docker.go
@@ -11,6 +11,7 @@ import (
"time"
"github.com/IceWhaleTech/CasaOS/model"
+ "github.com/IceWhaleTech/CasaOS/model/notify"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/docker"
upnp2 "github.com/IceWhaleTech/CasaOS/pkg/upnp"
@@ -143,10 +144,8 @@ func SpeedPush(c *gin.Context) {
// @Param env formData string false "环境变量"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
-// @Router /app/install/{id} [post]
+// @Router /app/install [post]
func InstallApp(c *gin.Context) {
- appId := c.Param("id")
- language := c.GetHeader("Language")
var appInfo model.ServerAppList
m := model.CustomizationPostData{}
c.BindJSON(&m)
@@ -156,7 +155,9 @@ func InstallApp(c *gin.Context) {
var dockerImageVersion string
//check app name is exist
-
+ if len(m.Protocol) == 0 {
+ m.Protocol = "http"
+ }
if m.Origin != "custom" {
oldName := m.Label
for i := 0; true; i++ {
@@ -175,7 +176,7 @@ func InstallApp(c *gin.Context) {
}
- //检查端口
+ //check port
if len(m.PortMap) > 0 && m.PortMap != "0" {
//c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
portMap, _ := strconv.Atoi(m.PortMap)
@@ -196,21 +197,6 @@ func InstallApp(c *gin.Context) {
dockerImage = m.Image
dockerImageVersion = "latest"
}
- if m.Origin != "custom" {
- appInfo = service.MyService.Casa().GetServerAppInfo(appId, "", language)
-
- } else {
-
- appInfo.Title = m.Label
- appInfo.Description = m.Description
- appInfo.Icon = m.Icon
- appInfo.ScreenshotLink = model.Strings{}
- appInfo.NetworkModel = m.NetworkModel
- appInfo.Tags = model.Strings{}
- appInfo.Tagline = ""
- appInfo.Index = m.Index
-
- }
for _, u := range m.Ports {
@@ -272,16 +258,16 @@ func InstallApp(c *gin.Context) {
m.CustomId = id
var relyMap = make(map[string]string)
go func() {
- installLog := model2.AppNotify{}
- installLog.State = 0
- installLog.CustomId = m.Label
- installLog.Message = "installing rely"
- installLog.Class = types.NOTIFY_APP
- installLog.Type = types.NOTIFY_TYPE_UNIMPORTANT
- installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
- installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
- installLog.Id = uuid.NewV4().String()
- service.MyService.Notify().AddLog(installLog)
+ // installLog := model2.AppNotify{}
+ // installLog.State = 0
+ // installLog.CustomId = m.Label
+ // installLog.Message = "installing rely"
+ // installLog.Class = types.NOTIFY_APP
+ // installLog.Type = types.NOTIFY_TYPE_UNIMPORTANT
+ // installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
+ // installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
+ // installLog.Id = uuid.NewV4().String()
+ // service.MyService.Notify().AddLog(installLog)
if m.Origin != "custom" {
for _, plugin := range appInfo.Plugins {
if plugin == "mysql" {
@@ -314,24 +300,26 @@ func InstallApp(c *gin.Context) {
} else {
docker_base.MysqlDelete(mysqlContainerId)
- installLog.State = 0
- installLog.Message = err.Error()
- service.MyService.Notify().UpdateLog(installLog)
+ // installLog.State = 0
+ // installLog.Message = err.Error()
+ // service.MyService.Notify().UpdateLog(installLog)
}
}
}
}
- installLog.Message = "pulling"
- service.MyService.Notify().UpdateLog(installLog)
-
// step:下载镜像
- err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, installLog)
+ err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, m.Icon, m.Label)
if err != nil {
- installLog.State = 0
- installLog.Message = err.Error()
- installLog.Type = types.NOTIFY_TYPE_ERROR
- service.MyService.Notify().UpdateLog(installLog)
+ notify := notify.Application{}
+ notify.Icon = m.Icon
+ notify.Name = m.Label
+ notify.State = "PULLING"
+ notify.Type = "INSTALL"
+ notify.Success = false
+ notify.Finished = false
+ notify.Message = err.Error()
+ service.MyService.Notify().SendInstallAppBySocket(notify)
return
}
@@ -339,35 +327,28 @@ func InstallApp(c *gin.Context) {
time.Sleep(time.Second)
}
- //if {
-
- //}
-
- //step:创建容器
- // networkName, err := service.MyService.Docker().GetNetWorkNameByNetWorkID(appInfo.NetworkModel)
- // if err != nil {
- // //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100)
- // installLog.State = 0
- // installLog.Speed = 75
- // installLog.Type = types.NOTIFY_TYPE_ERROR
- // installLog.Message = err.Error()
- // service.MyService.Notify().UpdateLog(installLog)
- // return
- // }
- containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, m, appInfo.NetworkModel)
- installLog.Name = appInfo.Title
- installLog.Icon = appInfo.Icon
+ _, err = service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, m, appInfo.NetworkModel)
if err != nil {
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100)
- installLog.State = 0
- installLog.Type = types.NOTIFY_TYPE_ERROR
- installLog.Message = err.Error()
- service.MyService.Notify().UpdateLog(installLog)
+ notify := notify.Application{}
+ notify.Icon = m.Icon
+ notify.Name = m.Label
+ notify.State = "STARTING"
+ notify.Type = "INSTALL"
+ notify.Success = false
+ notify.Finished = false
+ notify.Message = err.Error()
+ service.MyService.Notify().SendInstallAppBySocket(notify)
return
} else {
- //service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"starting\",\"speed\":80}", 100)
- installLog.Message = "starting"
- service.MyService.Notify().UpdateLog(installLog)
+ notify := notify.Application{}
+ notify.Icon = m.Icon
+ notify.Name = m.Label
+ notify.State = "STARTING"
+ notify.Type = "INSTALL"
+ notify.Success = true
+ notify.Finished = false
+ service.MyService.Notify().SendInstallAppBySocket(notify)
}
// echo -e "hellow\nworld" >>
@@ -376,23 +357,27 @@ func InstallApp(c *gin.Context) {
err = service.MyService.Docker().DockerContainerStart(m.Label)
if err != nil {
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":90}", 100)
- installLog.State = 0
- installLog.Type = types.NOTIFY_TYPE_ERROR
- installLog.Message = err.Error()
- service.MyService.Notify().UpdateLog(installLog)
+ notify := notify.Application{}
+ notify.Icon = m.Icon
+ notify.Name = m.Label
+ notify.State = "STARTING"
+ notify.Type = "INSTALL"
+ notify.Success = false
+ notify.Finished = false
+ notify.Message = err.Error()
+ service.MyService.Notify().SendInstallAppBySocket(notify)
return
} else {
- //service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"setting upnp\",\"speed\":90}", 100)
- if m.Origin != CUSTOM {
- installLog.Message = "setting upnp"
- } else {
- installLog.Message = "nearing completion"
- }
- service.MyService.Notify().UpdateLog(installLog)
+ // if m.Origin != CUSTOM {
+ // installLog.Message = "setting upnp"
+ // } else {
+ // installLog.Message = "nearing completion"
+ // }
+ // service.MyService.Notify().UpdateLog(installLog)
}
if m.Origin != CUSTOM {
- //step:启动upnp
+ //step:enable upnp
if m.EnableUPNP {
upnp, err := upnp2.Gateway()
if err == nil {
@@ -424,89 +409,49 @@ func InstallApp(c *gin.Context) {
}
}
- if err != nil {
- //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":95}", 100)
- installLog.State = 0
- installLog.Type = types.NOTIFY_TYPE_ERROR
- installLog.Message = err.Error()
- service.MyService.Notify().UpdateLog(installLog)
- } else {
- //service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"checking\",\"speed\":95}", 100)
- installLog.Message = "checking"
- service.MyService.Notify().UpdateLog(installLog)
- }
+ // if err != nil {
+ // //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":95}", 100)
+ // installLog.State = 0
+ // installLog.Type = types.NOTIFY_TYPE_ERROR
+ // installLog.Message = err.Error()
+ // service.MyService.Notify().UpdateLog(installLog)
+ // } else {
+ // //service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"checking\",\"speed\":95}", 100)
+ // installLog.Message = "checking"
+ // service.MyService.Notify().UpdateLog(installLog)
+ // }
}
}
//step: 启动成功 检查容器状态确认启动成功
container, err := service.MyService.Docker().DockerContainerInfo(m.Label)
if err != nil && container.ContainerJSONBase.State.Running {
- //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":100}", 100)
- installLog.State = 0
- installLog.Type = types.NOTIFY_TYPE_ERROR
- installLog.Message = err.Error()
- service.MyService.Notify().UpdateLog(installLog)
+ notify := notify.Application{}
+ notify.Icon = m.Icon
+ notify.Name = m.Label
+ notify.State = "INSTALLED"
+ notify.Type = "INSTALL"
+ notify.Success = false
+ notify.Finished = true
+ notify.Message = err.Error()
+ service.MyService.Notify().SendInstallAppBySocket(notify)
return
} else {
- //service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"installed\",\"speed\":100}", 100)
- installLog.Message = "installed"
- service.MyService.Notify().UpdateLog(installLog)
+ notify := notify.Application{}
+ notify.Icon = m.Icon
+ notify.Name = m.Label
+ notify.State = "INSTALLED"
+ notify.Type = "INSTALL"
+ notify.Success = true
+ notify.Finished = true
+ service.MyService.Notify().SendInstallAppBySocket(notify)
}
- rely := model.MapStrings{}
-
- copier.Copy(&rely, &relyMap)
// if m.Origin != "custom" {
// for i := 0; i < len(m.Volumes); i++ {
// m.Volumes[i].Path = docker.GetDir(id, m.Volumes[i].Path)
// }
// }
-
- portsStr, _ := json2.Marshal(m.Ports)
- envsStr, _ := json2.Marshal(m.Envs)
- volumesStr, _ := json2.Marshal(m.Volumes)
- devicesStr, _ := json2.Marshal(m.Devices)
- cmd, _ := json2.Marshal(m.Cmd)
- capAdd, _ := json.Marshal(m.CapAdd)
- //step: 保存数据到数据库
- md := model2.AppListDBModel{
- CustomId: "",
- Title: appInfo.Title,
- //ScreenshotLink: appInfo.ScreenshotLink,
- Slogan: appInfo.Tagline,
- Description: appInfo.Description,
- //Tags: appInfo.Tags,
- Icon: appInfo.Icon,
- Version: dockerImageVersion,
- ContainerId: containerId,
- Image: dockerImage,
- Index: appInfo.Index,
- //Port: m.Port,
- PortMap: m.PortMap,
- Label: m.Label,
- EnableUPNP: m.EnableUPNP,
- Ports: string(portsStr),
- Envs: string(envsStr),
- Volumes: string(volumesStr),
- Position: m.Position,
- NetModel: appInfo.NetworkModel,
- Restart: m.Restart,
- CpuShares: m.CpuShares,
- Memory: m.Memory,
- Devices: string(devicesStr),
- //Rely: rely,
- Origin: m.Origin,
- CreatedAt: 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" {
- // m.PortMap = m.Port
- //}
- fmt.Println(md)
//service.MyService.App().SaveContainer(md)
config.CasaOSGlobalVariables.AppChange = true
@@ -728,19 +673,15 @@ func UnInstallApp(c *gin.Context) {
return
}
- //step:删除容器
err = service.MyService.Docker().DockerContainerRemove(appId, false)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.UNINSTALL_APP_ERROR, Message: oasis_err2.GetMsg(oasis_err2.UNINSTALL_APP_ERROR), Data: err.Error()})
return
}
- //存在镜像正在使用的情况
- // step:删除镜像
- service.MyService.Docker().DockerImageRemove(info.Image)
+ // step:remove image
+ service.MyService.Docker().DockerImageRemove(info.Config.Image)
- //step: 删除本地数据
- //service.MyService.App().RemoveContainerById(appId)
if info.Config.Labels["origin"] != "custom" {
fmt.Println(info.HostConfig.Mounts)
//step: 删除文件夹
@@ -791,13 +732,14 @@ func UnInstallApp(c *gin.Context) {
//}
}
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)
-
+ notify := notify.Application{}
+ notify.Icon = info.Config.Labels["icon"]
+ notify.Name = strings.ReplaceAll(info.Name, "/", "")
+ notify.State = "FINISHED"
+ notify.Type = "UNINSTALL"
+ notify.Success = true
+ notify.Finished = true
+ service.MyService.Notify().SendUninstallAppBySocket(notify)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
@@ -1083,7 +1025,7 @@ func PutAppUpdate(c *gin.Context) {
}
imageLatest := strings.Split(inspect.Config.Image, ":")[0] + ":latest"
- err = service.MyService.Docker().DockerPullImage(imageLatest, model2.AppNotify{})
+ err = service.MyService.Docker().DockerPullImage(imageLatest, "", "")
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
return
@@ -1182,7 +1124,7 @@ func ContainerInfo(c *gin.Context) {
data := make(map[string]interface{}, 5)
data["app"] = appInfo
data["cpu"] = cpuModel
- data["memory"] = service.MyService.ZiMa().GetMemInfo().Total
+ data["memory"] = service.MyService.System().GetMemInfo().Total
data["container"] = json2.RawMessage(containerInfo)
data["info"] = con
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
@@ -1205,7 +1147,7 @@ func GetDockerInstallConfig(c *gin.Context) {
}
}
data["networks"] = list
- data["memory"] = service.MyService.ZiMa().GetMemInfo()
+ data["memory"] = service.MyService.System().GetMemInfo()
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
}
@@ -1257,12 +1199,20 @@ func ContainerUpdateInfo(c *gin.Context) {
// json2.Unmarshal([]byte(appInfo.Envs), &envs)
for _, v := range info.Config.Env {
-
- temp := model.Env{
- Name: strings.Split(v, "=")[0],
- Value: strings.Split(v, "=")[1],
+ showENV := info.Config.Labels["show_env"]
+ showENVList := strings.Split(showENV, ",")
+ showENVMap := make(map[string]string)
+ for _, name := range showENVList {
+ showENVMap[name] = "1"
}
- envs = append(envs, temp)
+ if _, ok := showENVMap[v]; ok {
+ temp := model.Env{
+ Name: strings.Split(v, "=")[0],
+ Value: strings.Split(v, "=")[1],
+ }
+ envs = append(envs, temp)
+ }
+
}
var vol model.PathArray
@@ -1309,6 +1259,7 @@ func ContainerUpdateInfo(c *gin.Context) {
m.Index = info.Config.Labels["index"]
m.Position = false
m.CustomId = info.Config.Labels["custom_id"]
+ m.Host = info.Config.Labels["host"]
if len(m.CustomId) == 0 {
m.CustomId = uuid.NewV4().String()
}
@@ -1317,6 +1268,11 @@ func ContainerUpdateInfo(c *gin.Context) {
m.HostName = info.Config.Hostname
m.Privileged = info.HostConfig.Privileged
+ m.Protocol = info.Config.Labels["protocol"]
+ if m.Protocol == "" {
+ m.Protocol = "http"
+ }
+
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: m})
}
diff --git a/route/v1/file.go b/route/v1/file.go
index 5dc7970..85edc6e 100644
--- a/route/v1/file.go
+++ b/route/v1/file.go
@@ -6,20 +6,24 @@ import (
"fmt"
"io"
"io/ioutil"
+ "log"
"net/http"
+ "net/url"
url2 "net/url"
"os"
"path"
+ "path/filepath"
"strconv"
"strings"
"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"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin"
- "github.com/spf13/afero"
+ uuid "github.com/satori/go.uuid"
)
func downloadReadFile(c *gin.Context) {
@@ -48,24 +52,6 @@ func downloadReadFile(c *gin.Context) {
}
}
-func downloadWriteFile(c *gin.Context) {
- //写文件
- var filename = "./output1.csv"
-
- file, err := os.Create(filename) //创建文件
- if err != nil {
- c.String(400, err.Error())
- return
- }
- buf := bufio.NewWriter(file) //创建新的 Writer 对象
- buf.WriteString("test")
- buf.Flush()
- defer file.Close()
-
- //返回文件流
- c.File(filename)
-}
-
// @Summary 读取文件
// @Produce application/json
// @Accept application/json
@@ -135,82 +121,106 @@ func GetLocalFile(c *gin.Context) {
// @Accept application/json
// @Tags file
// @Security ApiKeyAuth
-// @Param path query string true "path of file"
+// @Param t query string false "Compression format" Enums(zip,tar,targz)
+// @Param files query string true "file list eg: filename1,filename2,filename3 "
// @Success 200 {string} string "ok"
// @Router /file/download [get]
func GetDownloadFile(c *gin.Context) {
- filePath := c.Query("path")
- if len(filePath) == 0 {
+
+ t := c.Query("t")
+
+ files := c.Query("files")
+
+ if len(files) == 0 {
c.JSON(http.StatusOK, model.Result{
Success: oasis_err2.INVALID_PARAMS,
Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS),
})
return
}
- if !file.Exists(filePath) {
+ list := strings.Split(files, ",")
+ for _, v := range list {
+ if !file.Exists(v) {
+ c.JSON(http.StatusOK, model.Result{
+ Success: oasis_err2.FILE_DOES_NOT_EXIST,
+ Message: oasis_err2.GetMsg(oasis_err2.FILE_DOES_NOT_EXIST),
+ })
+ return
+ }
+ }
+ c.Header("Content-Type", "application/octet-stream")
+ c.Header("Content-Transfer-Encoding", "binary")
+ c.Header("Cache-Control", "private")
+ // handles only single files not folders and multiple files
+ if len(list) == 1 {
+
+ filePath := list[0]
+ info, err := os.Stat(filePath)
+ if err != nil {
+ c.JSON(http.StatusOK, model.Result{
+ Success: oasis_err2.FILE_DOES_NOT_EXIST,
+ Message: oasis_err2.GetMsg(oasis_err2.FILE_DOES_NOT_EXIST),
+ })
+ return
+ }
+ if !info.IsDir() {
+
+ //打开文件
+ fileTmp, _ := os.Open(filePath)
+ defer fileTmp.Close()
+
+ //获取文件的名称
+ fileName := path.Base(filePath)
+ c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
+ c.File(filePath)
+ return
+ }
+ }
+
+ extension, ar, err := file.GetCompressionAlgorithm(t)
+ if err != nil {
c.JSON(http.StatusOK, model.Result{
- Success: oasis_err2.FILE_DOES_NOT_EXIST,
- Message: oasis_err2.GetMsg(oasis_err2.FILE_DOES_NOT_EXIST),
+ Success: oasis_err2.INVALID_PARAMS,
+ Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS),
})
return
}
- //打开文件
- fileTmp, _ := os.Open(filePath)
- defer fileTmp.Close()
- //获取文件的名称
- fileName := path.Base(filePath)
- c.Header("Content-Type", "application/octet-stream")
- c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
- c.Header("Content-Transfer-Encoding", "binary")
- c.Header("Cache-Control", "no-cache")
- c.File(filePath)
+ err = ar.Create(c.Writer)
+ if err != nil {
+ c.JSON(http.StatusOK, model.Result{
+ Success: oasis_err.ERROR,
+ Message: oasis_err2.GetMsg(oasis_err2.ERROR),
+ Data: err.Error(),
+ })
+ return
+ }
+ defer ar.Close()
+ commonDir := file.CommonPrefix(filepath.Separator, list...)
+
+ currentPath := filepath.Base(commonDir)
+
+ name := "_" + currentPath
+ name += extension
+ c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(name))
+ for _, fname := range list {
+ err = file.AddFile(ar, fname, commonDir)
+ if err != nil {
+ log.Printf("Failed to archive %s: %v", fname, err)
+ }
+ }
+
}
-// @Summary download
-// @Produce application/json
-// @Accept application/json
-// @Tags file
-// @Security ApiKeyAuth
-// @Param path query string true "path of file"
-// @Success 200 {string} string "ok"
-// @Router /file/new/download [get]
-func GetFileDownloadNew(c *gin.Context) {
- filePath := c.Query("path")
- if len(filePath) == 0 {
- c.JSON(http.StatusOK, model.Result{
- Success: oasis_err2.INVALID_PARAMS,
- Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS),
- })
- return
- }
- if !file.Exists(filePath) {
- c.JSON(http.StatusOK, model.Result{
- Success: oasis_err2.FILE_DOES_NOT_EXIST,
- Message: oasis_err2.GetMsg(oasis_err2.FILE_DOES_NOT_EXIST),
- })
- return
- }
- //打开文件
- fileStat, _ := os.Stat(filePath)
- var AppFs = afero.NewOsFs()
- fileT, _ := AppFs.Open(filePath)
- //fileTmp, _ := os.Open(filePath)
- //defer fileTmp.Close()
- //获取文件的名称
- //fileName := path.Base(filePath)
+func GetDownloadSingleFile(c *gin.Context) {
+ filePath := c.Param("path")
+ fileTmp, _ := os.Open(filePath)
+ defer fileTmp.Close()
- //c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
- //在线
+ fileName := path.Base(filePath)
//c.Header("Content-Disposition", "inline")
- // extraHeaders := map[string]string{
- // "Content-Disposition": `attachment; filename="` + url2.PathEscape(fileName) + `"`,
- // }
-
- //c.Header("Cache-Control", "private")
- //c.Header("Content-Type", "application/octet-stream")
-
- http.ServeContent(c.Writer, c.Request, fileStat.Name(), fileStat.ModTime(), fileT)
+ c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
+ c.File(filePath)
}
// @Summary 获取目录列表
@@ -272,13 +282,15 @@ func DirPath(c *gin.Context) {
// @Accept application/json
// @Tags file
// @Security ApiKeyAuth
-// @Param oldpath formData string true "path of old"
-// @Param newpath formData string true "path of new"
+// @Param oldpath body string true "path of old"
+// @Param newpath body string true "path of new"
// @Success 200 {string} string "ok"
// @Router /file/rename [put]
func RenamePath(c *gin.Context) {
- op := c.PostForm("oldpath")
- np := c.PostForm("newpath")
+ json := make(map[string]string)
+ c.BindJSON(&json)
+ op := json["oldpath"]
+ np := json["newpath"]
if len(op) == 0 || len(np) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
@@ -289,45 +301,59 @@ func RenamePath(c *gin.Context) {
// @Summary create folder
// @Produce application/json
-// @Accept multipart/form-data
+// @Accept application/json
// @Tags file
// @Security ApiKeyAuth
-// @Param path formData string true "path of folder"
+// @Param path body string true "path of folder"
// @Success 200 {string} string "ok"
// @Router /file/mkdir [post]
func MkdirAll(c *gin.Context) {
- path := c.PostForm("path")
+ json := make(map[string]string)
+ c.BindJSON(&json)
+ path := json["path"]
var code int
if len(path) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
+ // decodedPath, err := url.QueryUnescape(path)
+ // if err != nil {
+ // c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
+ // return
+ // }
code, _ = service.MyService.ZiMa().MkdirAll(path)
c.JSON(http.StatusOK, model.Result{Success: code, Message: oasis_err2.GetMsg(code)})
}
// @Summary create file
// @Produce application/json
-// @Accept multipart/form-data
+// @Accept application/json
// @Tags file
// @Security ApiKeyAuth
-// @Param path formData string false "路径"
+// @Param path body string true "path of folder (path need to url encode)"
// @Success 200 {string} string "ok"
// @Router /file/create [post]
func PostCreateFile(c *gin.Context) {
- path := c.PostForm("path")
+ json := make(map[string]string)
+ c.BindJSON(&json)
+ path := json["path"]
var code int
if len(path) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
+ // decodedPath, err := url.QueryUnescape(path)
+ // if err != nil {
+ // c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
+ // return
+ // }
code, _ = service.MyService.ZiMa().CreateFile(path)
c.JSON(http.StatusOK, model.Result{Success: code, Message: oasis_err2.GetMsg(code)})
}
// @Summary upload file
// @Produce application/json
-// @Accept multipart/form-data
+// @Accept application/json
// @Tags file
// @Security ApiKeyAuth
// @Param path formData string false "file path"
@@ -432,90 +458,106 @@ func PostFileUpload(c *gin.Context) {
// @Summary copy or move file
// @Produce application/json
-// @Accept multipart/form-data
+// @Accept application/json
// @Tags file
// @Security ApiKeyAuth
-// @Param from formData string true "from path"
-// @Param to formData string true "to path"
-// @Param type formData string true "action" Enums(move,copy)
+// @Param body body model.FileOperate true "type: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 {
+
+ list := model.FileOperate{}
+ c.BindJSON(&list)
+
+ if len(list.Item) == 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)
+ var total int64 = 0
+ for i := 0; i < len(list.Item); i++ {
+
+ size, err := file.GetFileOrDirSize(list.Item[i].From)
if err != nil {
- c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
- return
+ continue
}
- } 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 {
- c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
- return
+ list.Item[i].Size = size
+ total += size
}
+
+ list.TotalSize = total
+ list.ProcessedSize = 0
+
+ uid := uuid.NewV4().String()
+ service.FileQueue[uid] = list
+ if len(service.FileQueue) == 1 {
+ go service.MyService.Notify().SendFileOperateNotify()
+ go service.CheckFileStatus()
+
+ }
+ go service.FileOperate(list)
+
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary delete file
// @Produce application/json
-// @Accept multipart/form-data
+// @Accept application/json
// @Tags file
// @Security ApiKeyAuth
-// @Param path query string true "path"
+// @Param body body string true "paths eg ["/a/b/c","/d/e/f"]"
// @Success 200 {string} string "ok"
// @Router /file/delete [delete]
func DeleteFile(c *gin.Context) {
- path := c.Query("path")
- //err := os.Remove(path)
- err := os.RemoveAll(path)
- if err != nil {
- fmt.Println(err)
- c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_DELETE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.FILE_DELETE_ERROR), Data: err})
+
+ paths := []string{}
+ c.BindJSON(&paths)
+ if len(paths) == 0 {
+ c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
+ // path := c.Query("path")
+
+ // paths := strings.Split(path, ",")
+
+ for _, v := range paths {
+ err := os.RemoveAll(v)
+ if err != nil {
+ c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_DELETE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.FILE_DELETE_ERROR), Data: err})
+ return
+ }
+ }
+
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary update file
// @Produce application/json
-// @Accept multipart/form-data
+// @Accept application/json
// @Tags file
// @Security ApiKeyAuth
-// @Param path formData string true "path"
-// @Param content formData string true "content"
+// @Param path body string true "path"
+// @Param content body string true "content"
// @Success 200 {string} string "ok"
// @Router /file/update [put]
func PutFileContent(c *gin.Context) {
- path := c.PostForm("path")
- content := c.PostForm("content")
- if !file.Exists(path) {
+
+ fi := model.FileUpdate{}
+ c.BindJSON(&fi)
+
+ // path := c.PostForm("path")
+ // content := c.PostForm("content")
+ if !file.Exists(fi.FilePath) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_ALREADY_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
return
}
//err := os.Remove(path)
- err := os.RemoveAll(path)
+ err := os.RemoveAll(fi.FilePath)
if err != nil {
fmt.Println(err)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_DELETE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.FILE_DELETE_ERROR), Data: err})
return
}
- err = file.CreateFileAndWriteContent(path, content)
+ err = file.CreateFileAndWriteContent(fi.FilePath, fi.FileContent)
if err != nil {
fmt.Println(err)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err})
diff --git a/route/v1/notify.go b/route/v1/notify.go
index 18752c5..bcf5f90 100644
--- a/route/v1/notify.go
+++ b/route/v1/notify.go
@@ -1,62 +1,5 @@
package v1
-import (
- "fmt"
- "net/http"
-
- "github.com/IceWhaleTech/CasaOS/service"
- "github.com/IceWhaleTech/CasaOS/types"
- "github.com/gin-gonic/gin"
- "github.com/gorilla/websocket"
-)
-
-var upGrader = websocket.Upgrader{
- CheckOrigin: func(r *http.Request) bool {
- return true
- },
-}
-
-// @Summary websocket 接口,连接成功后发送一个"notify"字符串
-// @Produce application/json
-// @Accept application/json
-// @Tags notify
-// @Security ApiKeyAuth
-// @Param token path string true "token"
-// @Success 200 {string} string "ok"
-// @Router /notify/ws [get]
-func NotifyWS(c *gin.Context) {
- //升级get请求为webSocket协议
- ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
- if err != nil {
- return
- }
- defer ws.Close()
- service.WebSocketConns = append(service.WebSocketConns, ws)
-
- if !service.SocketRun {
- service.SocketRun = true
- service.SendMeg()
- }
- for {
- mt, message, err := ws.ReadMessage()
- fmt.Println(mt, message, err)
- }
+func aaa() {
}
-
-// @Summary 标记notify已读
-// @Produce application/json
-// @Accept application/json
-// @Tags notify
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /notify/read/{id} [put]
-func PutNotifyRead(c *gin.Context) {
- id := c.Param("id")
- // if len(id) == 0 {
- // c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
- // return
- // }
- fmt.Println(id)
- service.MyService.Notify().MarkRead(id, types.NOTIFY_READ)
-}
diff --git a/route/v1/notify_old.go b/route/v1/notify_old.go
new file mode 100644
index 0000000..18752c5
--- /dev/null
+++ b/route/v1/notify_old.go
@@ -0,0 +1,62 @@
+package v1
+
+import (
+ "fmt"
+ "net/http"
+
+ "github.com/IceWhaleTech/CasaOS/service"
+ "github.com/IceWhaleTech/CasaOS/types"
+ "github.com/gin-gonic/gin"
+ "github.com/gorilla/websocket"
+)
+
+var upGrader = websocket.Upgrader{
+ CheckOrigin: func(r *http.Request) bool {
+ return true
+ },
+}
+
+// @Summary websocket 接口,连接成功后发送一个"notify"字符串
+// @Produce application/json
+// @Accept application/json
+// @Tags notify
+// @Security ApiKeyAuth
+// @Param token path string true "token"
+// @Success 200 {string} string "ok"
+// @Router /notify/ws [get]
+func NotifyWS(c *gin.Context) {
+ //升级get请求为webSocket协议
+ ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
+ if err != nil {
+ return
+ }
+ defer ws.Close()
+ service.WebSocketConns = append(service.WebSocketConns, ws)
+
+ if !service.SocketRun {
+ service.SocketRun = true
+ service.SendMeg()
+ }
+ for {
+ mt, message, err := ws.ReadMessage()
+ fmt.Println(mt, message, err)
+ }
+
+}
+
+// @Summary 标记notify已读
+// @Produce application/json
+// @Accept application/json
+// @Tags notify
+// @Security ApiKeyAuth
+// @Success 200 {string} string "ok"
+// @Router /notify/read/{id} [put]
+func PutNotifyRead(c *gin.Context) {
+ id := c.Param("id")
+ // if len(id) == 0 {
+ // c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
+ // return
+ // }
+ fmt.Println(id)
+ service.MyService.Notify().MarkRead(id, types.NOTIFY_READ)
+}
diff --git a/route/v1/system.go b/route/v1/system.go
index d63afa7..ad26cfe 100644
--- a/route/v1/system.go
+++ b/route/v1/system.go
@@ -452,18 +452,18 @@ func Info(c *gin.Context) {
}
}
data["usb"] = usb
- cpu := service.MyService.ZiMa().GetCpuPercent()
- num := service.MyService.ZiMa().GetCpuCoreNum()
+ cpu := service.MyService.System().GetCpuPercent()
+ num := service.MyService.System().GetCpuCoreNum()
cpuData := make(map[string]interface{})
cpuData["percent"] = cpu
cpuData["num"] = num
data["cpu"] = cpuData
- data["mem"] = service.MyService.ZiMa().GetMemInfo()
+ data["mem"] = service.MyService.System().GetMemInfo()
//拼装网络信息
- netList := service.MyService.ZiMa().GetNetInfo()
+ netList := service.MyService.System().GetNetInfo()
newNet := []model.IOCountersStat{}
- nets := service.MyService.ZiMa().GetNet(true)
+ nets := service.MyService.System().GetNet(true)
for _, n := range netList {
for _, netCardName := range nets {
if n.Name == netCardName {
@@ -480,3 +480,20 @@ func Info(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
}
+
+// @Summary Get notification port
+// @Produce application/json
+// @Accept application/json
+// @Tags sys
+// @Security ApiKeyAuth
+// @Success 200 {string} string "ok"
+// @Router /sys/socket/port [get]
+func GetSystemSocketPort(c *gin.Context) {
+
+ c.JSON(http.StatusOK,
+ model.Result{
+ Success: oasis_err.SUCCESS,
+ Message: oasis_err.GetMsg(oasis_err.SUCCESS),
+ Data: config.ServerInfo.SocketPort,
+ })
+}
diff --git a/route/v1/zima_info.go b/route/v1/zima_info.go
index 91bfda6..a8f5eea 100644
--- a/route/v1/zima_info.go
+++ b/route/v1/zima_info.go
@@ -1,3 +1,13 @@
+/*
+ * @Author: LinkLeong link@icewhale.com
+ * @Date: 2021-09-30 18:18:14
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-05-27 18:07:13
+ * @FilePath: /CasaOS/route/v1/zima_info.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
package v1
import (
@@ -21,8 +31,8 @@ import (
// @Router /zima/getcpuinfo [get]
func CupInfo(c *gin.Context) {
//检查参数是否正确
- cpu := service.MyService.ZiMa().GetCpuPercent()
- num := service.MyService.ZiMa().GetCpuCoreNum()
+ cpu := service.MyService.System().GetCpuPercent()
+ num := service.MyService.System().GetCpuCoreNum()
data := make(map[string]interface{})
data["percent"] = cpu
data["num"] = num
@@ -40,7 +50,7 @@ func CupInfo(c *gin.Context) {
func MemInfo(c *gin.Context) {
//检查参数是否正确
- mem := service.MyService.ZiMa().GetMemInfo()
+ mem := service.MyService.System().GetMemInfo()
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: mem})
}
@@ -65,11 +75,11 @@ func DiskInfo(c *gin.Context) {
// @Success 200 {string} string "ok"
// @Router /zima/getnetinfo [get]
func NetInfo(c *gin.Context) {
- netList := service.MyService.ZiMa().GetNetInfo()
+ netList := service.MyService.System().GetNetInfo()
newNet := []model.IOCountersStat{}
for _, n := range netList {
- for _, netCardName := range service.MyService.ZiMa().GetNet(true) {
+ for _, netCardName := range service.MyService.System().GetNet(true) {
if n.Name == netCardName {
item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name))
diff --git a/service/app.go b/service/app.go
index cbcf52a..751799e 100644
--- a/service/app.go
+++ b/service/app.go
@@ -215,6 +215,8 @@ func (a *appStruct) GetMyList(index, size int, position bool) (*[]model2.MyAppLi
Index: "/",
Image: "",
Type: v.Type,
+ Host: "",
+ Protocol: "",
NewVersion: false,
})
}
@@ -239,6 +241,8 @@ func (a *appStruct) GetMyList(index, size int, position bool) (*[]model2.MyAppLi
Type: m.Labels["origin"],
//Slogan: m.Slogan,
//Rely: m.Rely,
+ Host: m.Labels["host"],
+ Protocol: m.Labels["protocol"],
})
} else {
unTranslation = append(unTranslation, model2.MyAppList{
@@ -249,6 +253,8 @@ func (a *appStruct) GetMyList(index, size int, position bool) (*[]model2.MyAppLi
Id: m.ID,
Port: "",
NewVersion: false,
+ Host: "",
+ Protocol: "",
Image: m.Image,
})
}
diff --git a/service/casa.go b/service/casa.go
index ff7aa9d..682eef2 100644
--- a/service/casa.go
+++ b/service/casa.go
@@ -83,17 +83,26 @@ func (o *casaService) GetServerList(index, size, tp, categoryId, key, language s
return
}
-func (o *casaService) GetServerCategoryList() []model.ServerCategoryList {
+func (o *casaService) GetServerCategoryList() (list []model.ServerCategoryList) {
+
+ keyName := fmt.Sprintf("category_list")
+ if result, ok := Cache.Get(keyName); ok {
+ res, ok := result.(string)
+ if ok {
+ json2.Unmarshal([]byte(gjson.Get(res, "data").String()), &list)
+ return list
+ }
+ }
head := make(map[string]string)
head["Authorization"] = GetToken()
listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/category", head)
- list := []model.ServerCategoryList{}
-
json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &list)
-
+ if len(list) > 0 {
+ Cache.SetDefault(keyName, listS)
+ }
return list
}
func (o *casaService) GetServerAppInfo(id, t string, language string) model.ServerAppList {
diff --git a/service/docker.go b/service/docker.go
index 2fa4f06..2e1ea20 100644
--- a/service/docker.go
+++ b/service/docker.go
@@ -7,11 +7,9 @@ import (
"encoding/binary"
json2 "encoding/json"
"fmt"
- "reflect"
"syscall"
- model2 "github.com/IceWhaleTech/CasaOS/service/model"
- types2 "github.com/IceWhaleTech/CasaOS/types"
+ "github.com/IceWhaleTech/CasaOS/model/notify"
"github.com/containerd/containerd"
"github.com/containerd/containerd/cio"
"github.com/containerd/containerd/namespaces"
@@ -44,7 +42,7 @@ import (
)
type DockerService interface {
- DockerPullImage(imageName string, m model2.AppNotify) error
+ DockerPullImage(imageName string, icon, name string) error
IsExistImage(imageName string) bool
DockerContainerCreate(imageName string, m model.CustomizationPostData, net string) (containerId string, err error)
DockerContainerCopyCreate(info *types.ContainerJSON) (containerId string, err error)
@@ -319,7 +317,7 @@ func (ds *dockerService) IsExistImage(imageName string) bool {
}
//安装镜像
-func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) error {
+func (ds *dockerService) DockerPullImage(imageName string, icon, name string) error {
cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil {
return err
@@ -334,7 +332,8 @@ func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) e
return err
}
- buf := make([]byte, 256)
+ //io.Copy()
+ buf := make([]byte, 2048*4)
for {
n, err := out.Read(buf)
if err != nil {
@@ -343,11 +342,16 @@ func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) e
}
break
}
- if !reflect.DeepEqual(m, model2.AppNotify{}) {
- m.Type = types2.NOTIFY_TYPE_INSTALL_LOG
- m.State = 0
- m.Message = string(buf[:n])
- MyService.Notify().UpdateLog(m)
+ if len(icon) > 0 && len(name) > 0 {
+ notify := notify.Application{}
+ notify.Icon = icon
+ notify.Name = name
+ notify.State = "PULLING"
+ notify.Type = "INSTALL"
+ notify.Finished = false
+ notify.Success = true
+ notify.Message = string(buf[:n])
+ MyService.Notify().SendInstallAppBySocket(notify)
}
}
@@ -433,12 +437,14 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
}
var envArr []string
+ var showENV []string
for _, e := range m.Envs {
if strings.HasPrefix(e.Value, "$") {
envArr = append(envArr, e.Name+"="+env_helper.ReplaceDefaultENV(e.Value, MyService.System().GetTimeZone()))
continue
}
if len(e.Value) > 0 {
+ showENV = append(showENV, e.Name)
if e.Value == "port_map" {
envArr = append(envArr, e.Name+"="+m.PortMap)
continue
@@ -530,6 +536,9 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
config.Labels["desc"] = m.Description
config.Labels["index"] = m.Index
config.Labels["custom_id"] = m.CustomId
+ config.Labels["show_env"] = strings.Join(showENV, ",")
+ config.Labels["protocol"] = m.Protocol
+ config.Labels["host"] = m.Host
//config.Labels["order"] = strconv.Itoa(MyService.App().GetCasaOSCount() + 1)
hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: container.NetworkMode(net), Privileged: m.Privileged, CapAdd: m.CapAdd}
//if net != "host" {
diff --git a/service/file.go b/service/file.go
index 7130cca..d35c70d 100644
--- a/service/file.go
+++ b/service/file.go
@@ -1,38 +1,28 @@
+/*
+ * @Author: LinkLeong link@icewhale.com
+ * @Date: 2021-12-20 14:15:46
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-05-30 18:49:46
+ * @FilePath: /CasaOS/service/file.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
package service
import (
"context"
"io"
+ "os"
+ "path/filepath"
+ "strings"
+ "time"
+
+ "github.com/IceWhaleTech/CasaOS/model"
+ "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
)
-// type InteruptReader struct {
-// r io.Reader
-// interupt chan int
-// }
-
-// func NewInteruptReader(r io.Reader) InteruptReader {
-// return InteruptReader{
-// r,
-// make(chan int),
-// }
-// }
-
-// func (r InteruptReader) Read(p []byte) (n int, err error) {
-// if r.r == nil {
-// return 0, io.EOF
-// }
-// select {
-// case <-r.interupt:
-// return r.r.Read(p)
-// default:
-// r.r = nil
-// return 0, io.EOF
-// }
-// }
-
-// func (r InteruptReader) Cancel() {
-// r.interupt <- 0
-// }
+var FileQueue map[string]model.FileOperate
type reader struct {
ctx context.Context
@@ -83,3 +73,55 @@ func (w *writer) Write(p []byte) (n int, err error) {
return w.w.Write(p)
}
}
+func FileOperate(list model.FileOperate) {
+ for _, v := range list.Item {
+ if list.Type == "move" {
+ lastPath := v.From[strings.LastIndex(v.From, "/")+1:]
+ if !file.CheckNotExist(list.To + "/" + lastPath) {
+ continue
+ }
+ err := os.Rename(v.From, list.To+"/"+lastPath)
+ if err != nil {
+ continue
+ }
+ } else if list.Type == "copy" {
+ err := file.CopyDir(v.From, list.To)
+ if err != nil {
+ continue
+ }
+ } else {
+ continue
+ }
+ }
+}
+
+// file move or copy and send notify
+func CheckFileStatus() {
+ for {
+ if len(FileQueue) == 0 {
+ return
+ }
+ for k, v := range FileQueue {
+ var total int64 = 0
+ for i := 0; i < len(v.Item); i++ {
+ if !v.Item[i].Finished {
+ size, err := file.GetFileOrDirSize(v.To + "/" + filepath.Base(v.Item[i].From))
+ if err != nil {
+ continue
+ }
+ v.Item[i].ProcessedSize = size
+ if size == v.Item[i].Size {
+ v.Item[i].Finished = true
+ }
+ total += size
+ } else {
+ total += v.Item[i].ProcessedSize
+ }
+
+ }
+ v.ProcessedSize = total
+ FileQueue[k] = v
+ }
+ time.Sleep(time.Second * 3)
+ }
+}
diff --git a/service/model/o_container.go b/service/model/o_container.go
index 5f868a6..5d4de3a 100644
--- a/service/model/o_container.go
+++ b/service/model/o_container.go
@@ -1,3 +1,13 @@
+/*
+ * @Author: LinkLeong link@icewhale.com
+ * @Date: 2022-05-13 18:15:46
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-05-30 17:33:21
+ * @FilePath: /CasaOS/service/model/o_container.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
package model
const CONTAINERTABLENAME = "o_container"
@@ -64,4 +74,6 @@ type MyAppList struct {
Image string `json:"image"`
Volumes string `json:"volumes"`
NewVersion bool `json:"new_version"`
+ Host string `json:"host"`
+ Protocol string `json:"protocol"`
}
diff --git a/service/notify.go b/service/notify.go
index fb56c76..4f1ece4 100644
--- a/service/notify.go
+++ b/service/notify.go
@@ -2,14 +2,23 @@ package service
import (
json2 "encoding/json"
+ "fmt"
"time"
+ model2 "github.com/IceWhaleTech/CasaOS/model"
+ "github.com/IceWhaleTech/CasaOS/model/notify"
"github.com/IceWhaleTech/CasaOS/service/model"
"github.com/IceWhaleTech/CasaOS/types"
+ "github.com/ambelovsky/gosf"
+ socketio "github.com/googollee/go-socket.io"
"github.com/gorilla/websocket"
+ "github.com/shirou/gopsutil/v3/mem"
"gorm.io/gorm"
)
+var NotifyMsg chan notify.Message
+var ClientCount int = 0
+
type NotifyServer interface {
GetLog(id string) model.AppNotify
AddLog(log model.AppNotify)
@@ -18,13 +27,208 @@ type NotifyServer interface {
DelLog(id string)
GetList(c int) (list []model.AppNotify)
MarkRead(id string, state int)
- SendText(m model.AppNotify)
+ // SendText(m model.AppNotify)
+ SendUninstallAppBySocket(app notify.Application)
+ SendNetInfoBySocket(netList []model2.IOCountersStat)
+ SendCPUInfoBySocket(cpu map[string]interface{})
+ SendMemInfoBySocket(mem *mem.VirtualMemoryStat)
+ SendUSBInfoBySocket(list []model2.DriveUSB)
+ SendDiskInfoBySocket(disk model2.Summary)
+ SendPersonStatusBySocket(status notify.Person)
+ SendFileOperateNotify()
+ SendInstallAppBySocket(app notify.Application)
}
type notifyServer struct {
db *gorm.DB
}
+// Send periodic broadcast messages
+func (i *notifyServer) SendFileOperateNotify() {
+ for {
+ if len(FileQueue) == 0 {
+ return
+ }
+ listMsg := make(map[string]interface{})
+ model := notify.NotifyModel{}
+ model.State = "NORMAL"
+ list := []notify.File{}
+ for k, v := range FileQueue {
+ task := notify.File{}
+ task.Id = k
+ task.ProcessedSize = v.ProcessedSize
+ task.TotalSize = v.TotalSize
+ task.To = v.To
+ if task.ProcessedSize == 0 {
+ task.Status = "STARTING"
+ } else {
+ task.Status = "PROCESSING"
+ }
+ if v.ProcessedSize == v.TotalSize {
+ task.Finished = true
+ task.Status = "FINISHED"
+ delete(FileQueue, k)
+ list = append(list, task)
+ break
+ }
+ for _, v := range v.Item {
+ if v.Size != v.ProcessedSize {
+ task.ProcessingPath = v.From
+ break
+ }
+ }
+
+ list = append(list, task)
+ }
+ model.Data = list
+
+ listMsg["file_operate"] = model
+
+ msg := gosf.Message{}
+ msg.Success = true
+ msg.Body = listMsg
+ msg.Text = "file_operate"
+
+ notify := notify.Message{}
+ notify.Path = "file_operate"
+ notify.Msg = msg
+ NotifyMsg <- notify
+ time.Sleep(time.Second * 3)
+ }
+}
+
+func (i *notifyServer) SendPersonStatusBySocket(status notify.Person) {
+ body := make(map[string]interface{})
+ body["data"] = status
+
+ msg := gosf.Message{}
+ msg.Body = body
+ msg.Success = true
+ msg.Text = "person_status"
+
+ notify := notify.Message{}
+ notify.Path = "person_status"
+ notify.Msg = msg
+
+ NotifyMsg <- notify
+}
+
+func (i *notifyServer) SendDiskInfoBySocket(disk model2.Summary) {
+ body := make(map[string]interface{})
+ body["data"] = disk
+
+ msg := gosf.Message{}
+ msg.Body = body
+ msg.Success = true
+ msg.Text = "sys_disk"
+
+ notify := notify.Message{}
+ notify.Path = "sys_disk"
+ notify.Msg = msg
+
+ NotifyMsg <- notify
+}
+
+func (i *notifyServer) SendUSBInfoBySocket(list []model2.DriveUSB) {
+ body := make(map[string]interface{})
+ body["data"] = list
+
+ msg := gosf.Message{}
+ msg.Body = body
+ msg.Success = true
+ msg.Text = "sys_usb"
+
+ notify := notify.Message{}
+ notify.Path = "sys_usb"
+ notify.Msg = msg
+
+ NotifyMsg <- notify
+}
+
+func (i *notifyServer) SendMemInfoBySocket(mem *mem.VirtualMemoryStat) {
+ body := make(map[string]interface{})
+ body["data"] = mem
+
+ msg := gosf.Message{}
+ msg.Body = body
+ msg.Success = true
+ msg.Text = "sys_mem"
+
+ notify := notify.Message{}
+ notify.Path = "sys_mem"
+ notify.Msg = msg
+
+ NotifyMsg <- notify
+}
+
+func (i *notifyServer) SendInstallAppBySocket(app notify.Application) {
+ body := make(map[string]interface{})
+ body["data"] = app
+
+ msg := gosf.Message{}
+ msg.Body = body
+ msg.Success = true
+ msg.Text = "app_install"
+
+ notify := notify.Message{}
+ notify.Path = "app_install"
+ notify.Msg = msg
+
+ NotifyMsg <- notify
+}
+
+func (i *notifyServer) SendCPUInfoBySocket(cpu map[string]interface{}) {
+ body := make(map[string]interface{})
+ body["data"] = cpu
+
+ msg := gosf.Message{}
+ msg.Body = body
+ msg.Success = true
+ msg.Text = "sys_cpu"
+
+ notify := notify.Message{}
+ notify.Path = "sys_cpu"
+ notify.Msg = msg
+
+ NotifyMsg <- notify
+}
+func (i *notifyServer) SendNetInfoBySocket(netList []model2.IOCountersStat) {
+ body := make(map[string]interface{})
+ body["data"] = netList
+
+ msg := gosf.Message{}
+ msg.Body = body
+ msg.Success = true
+ msg.Text = "sys_net"
+
+ notify := notify.Message{}
+ notify.Path = "sys_net"
+ notify.Msg = msg
+
+ NotifyMsg <- notify
+}
+
+func (i *notifyServer) SendUninstallAppBySocket(app notify.Application) {
+ body := make(map[string]interface{})
+ body["data"] = app
+
+ msg := gosf.Message{}
+ msg.Body = body
+ msg.Success = true
+ msg.Text = "app_uninstall"
+
+ notify := notify.Message{}
+ notify.Path = "app_uninstall"
+ notify.Msg = msg
+
+ NotifyMsg <- notify
+}
+
+func (i *notifyServer) SSR() {
+ server := socketio.NewServer(nil)
+ fmt.Println(server)
+}
+
func (i notifyServer) GetList(c int) (list []model.AppNotify) {
i.db.Where("class = ?", c).Where(i.db.Where("state = ?", types.NOTIFY_DYNAMICE).Or("state = ?", types.NOTIFY_UNREAD)).Find(&list)
return
@@ -103,25 +307,25 @@ func SendMeg() {
// }
}
-func (i notifyServer) SendText(m model.AppNotify) {
- list := []model.AppNotify{}
- list = append(list, m)
- json, _ := json2.Marshal(list)
- var temp []*websocket.Conn
- for _, v := range WebSocketConns {
+// func (i notifyServer) SendText(m model.AppNotify) {
+// list := []model.AppNotify{}
+// list = append(list, m)
+// json, _ := json2.Marshal(list)
+// var temp []*websocket.Conn
+// for _, v := range WebSocketConns {
- err := v.WriteMessage(1, json)
- if err == nil {
- temp = append(temp, v)
- }
- }
- WebSocketConns = temp
+// err := v.WriteMessage(1, json)
+// if err == nil {
+// temp = append(temp, v)
+// }
+// }
+// WebSocketConns = temp
- if len(WebSocketConns) == 0 {
- SocketRun = false
- }
+// if len(WebSocketConns) == 0 {
+// SocketRun = false
+// }
-}
+// }
func NewNotifyService(db *gorm.DB) NotifyServer {
return ¬ifyServer{db: db}
diff --git a/service/system.go b/service/system.go
index 75fd129..88bfaba 100644
--- a/service/system.go
+++ b/service/system.go
@@ -1,14 +1,19 @@
package service
import (
+ "fmt"
"io/ioutil"
- "net"
+ net2 "net"
"os"
+ "strconv"
"github.com/IceWhaleTech/CasaOS/pkg/config"
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
+ "github.com/shirou/gopsutil/v3/cpu"
+ "github.com/shirou/gopsutil/v3/mem"
+ "github.com/shirou/gopsutil/v3/net"
)
type SystemService interface {
@@ -23,11 +28,46 @@ type SystemService interface {
ExecUSBAutoMountShell(state string)
UpAppOrderFile(str string)
GetAppOrderFile() []byte
+ GetNet(physics bool) []string
+ GetNetInfo() []net.IOCountersStat
+ GetCpuCoreNum() int
+ GetCpuPercent() float64
+ GetMemInfo() *mem.VirtualMemoryStat
}
type systemService struct {
log loger.OLog
}
+func (c *systemService) GetMemInfo() *mem.VirtualMemoryStat {
+ memInfo, _ := mem.VirtualMemory()
+ memInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", memInfo.UsedPercent), 64)
+ return memInfo
+}
+
+func (c *systemService) GetCpuPercent() float64 {
+ percent, _ := cpu.Percent(0, false)
+ value, _ := strconv.ParseFloat(fmt.Sprintf("%.1f", percent[0]), 64)
+ return value
+}
+
+func (c *systemService) GetCpuCoreNum() int {
+ count, _ := cpu.Counts(false)
+ return count
+}
+
+func (c *systemService) GetNetInfo() []net.IOCountersStat {
+ parts, _ := net.IOCounters(true)
+ //fmt.Println(net.ConntrackStatsWithContext(true))
+ return parts
+}
+func (c *systemService) GetNet(physics bool) []string {
+ t := "1"
+ if physics {
+ t = "2"
+ }
+ return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetNetCard " + t)
+}
+
func (s *systemService) UpdateSystemVersion(version string) {
//command2.OnlyExec(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version)
//s.log.Error(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version)
@@ -99,12 +139,12 @@ func (s *systemService) GetCasaOSLogs(lineNumber int) string {
func GetDeviceAllIP() []string {
var address []string
- addrs, err := net.InterfaceAddrs()
+ addrs, err := net2.InterfaceAddrs()
if err != nil {
return address
}
for _, a := range addrs {
- if ipNet, ok := a.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
+ if ipNet, ok := a.(*net2.IPNet); ok && !ipNet.IP.IsLoopback() {
if ipNet.IP.To16() != nil {
address = append(address, ipNet.IP.String())
}
diff --git a/service/udpconn.go b/service/udpconn.go
index 3bee999..eddbad5 100644
--- a/service/udpconn.go
+++ b/service/udpconn.go
@@ -17,6 +17,7 @@ import (
"time"
"github.com/IceWhaleTech/CasaOS/model"
+ "github.com/IceWhaleTech/CasaOS/model/notify"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/quic_helper"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
@@ -92,7 +93,7 @@ func UDPSendData(msg model.MessageModel, localFilePath string) error {
}
func Dial(msg model.MessageModel, server bool) (m model.MessageModel, err error) {
- ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+ ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second)
defer cancel()
Message = make(chan model.MessageModel)
_, port, err := net.SplitHostPort(UDPConn.LocalAddr().String())
@@ -236,20 +237,20 @@ func ReadContent(stream quic.Stream) {
Message <- m
break
} else if m.Type == types.PERSONGETIP {
- notify := model2.AppNotify{}
- notify.CustomId = m.From
+ notify := notify.Person{}
+ notify.ShareId = m.From
if len(m.Data.(string)) == 0 {
if _, ok := UDPAddressMap[m.From]; ok {
- notify.Type = types.NOTIFY_TYPE_PERSION_FIRNED_LEAVE
- go MyService.Notify().SendText(notify)
+ notify.Type = "OFFLINE"
+ go MyService.Notify().SendPersonStatusBySocket(notify)
}
delete(UDPAddressMap, m.From)
Message <- m
break
}
if _, ok := UDPAddressMap[m.From]; !ok {
- notify.Type = types.NOTIFY_TYPE_PERSION_FIRNED_LIVE
- go MyService.Notify().SendText(notify)
+ notify.Type = "ONLINE"
+ go MyService.Notify().SendPersonStatusBySocket(notify)
}
UDPAddressMap[m.From] = m.Data.(string)
if config.ServerInfo.Token != m.From && strings.Split(m.Data.(string), ":")[0] == strings.Split(UDPAddressMap[config.ServerInfo.Token], ":")[0] {
@@ -330,10 +331,10 @@ func LoopFriend() {
data, err := Dial(msg, false)
if err != nil || reflect.DeepEqual(data, model.MessageModel{}) || len(data.Data.(string)) == 0 {
if oldIP == UDPAddressMap[list[i].Token] {
- notify := model2.AppNotify{}
- notify.CustomId = data.From
- notify.Type = types.NOTIFY_TYPE_PERSION_FIRNED_LEAVE
- go MyService.Notify().SendText(notify)
+ notify := notify.Person{}
+ notify.ShareId = data.From
+ notify.Type = "LEAVE"
+ go MyService.Notify().SendPersonStatusBySocket(notify)
delete(UDPAddressMap, list[i].Token)
diff --git a/service/zima_info.go b/service/zima_info.go
index ceb2545..ec1a44f 100644
--- a/service/zima_info.go
+++ b/service/zima_info.go
@@ -9,7 +9,6 @@ import (
"strconv"
"strings"
"time"
- "unsafe"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
@@ -19,18 +18,12 @@ import (
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/disk"
"github.com/shirou/gopsutil/v3/host"
- "github.com/shirou/gopsutil/v3/mem"
- "github.com/shirou/gopsutil/v3/net"
)
//系统信息
type ZiMaService interface {
- GetCpuPercent() float64
- GetCpuCoreNum() int
- GetMemInfo() *mem.VirtualMemoryStat
GetDiskInfo() *disk.UsageStat
- GetNetInfo() []net.IOCountersStat
- GetNet(physics bool) []string
+
GetNetState(name string) string
GetSysInfo() host.InfoStat
GetDirPath(path string) []model.Path
@@ -47,32 +40,12 @@ var NetArray [][]model.IOCountersStat
type zima struct {
}
-//获取cpu占用率
-func (c *zima) GetCpuPercent() float64 {
- percent, _ := cpu.Percent(0, false)
- value, _ := strconv.ParseFloat(fmt.Sprintf("%.1f", percent[0]), 64)
- return value
-}
-
-//获取物理核心数
-func (c *zima) GetCpuCoreNum() int {
- count, _ := cpu.Counts(false)
- return count
-}
-
//cpu详情
func (c *zima) GetCpuInfo() []cpu.InfoStat {
info, _ := cpu.Info()
return info
}
-//获取内存详情
-func (c *zima) GetMemInfo() *mem.VirtualMemoryStat {
- memInfo, _ := mem.VirtualMemory()
- memInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", memInfo.UsedPercent), 64)
- return memInfo
-}
-
//获取硬盘详情
func (c *zima) GetDiskInfo() *disk.UsageStat {
path := "/"
@@ -141,15 +114,6 @@ func (c *zima) GetSysInfo() host.InfoStat {
return *info
}
-//shell脚本参数 {1:虚拟网卡 2:物理网卡}
-func (c *zima) GetNet(physics bool) []string {
- t := "1"
- if physics {
- t = "2"
- }
- return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetNetCard " + t)
-}
-
func (c *zima) GetDeviceTree() string {
return command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetDeviceTree")
}
@@ -159,13 +123,6 @@ func (c *zima) GetNetState(name string) string {
return command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;CatNetCardState " + name)
}
-//网络信息
-func (c *zima) GetNetInfo() []net.IOCountersStat {
- parts, _ := net.IOCounters(true)
- //fmt.Println(net.ConntrackStatsWithContext(true))
- return parts
-}
-
//mkdir
func (c *zima) MkdirAll(path string) (int, error) {
_, err := os.Stat(path)
@@ -219,40 +176,40 @@ func NewZiMaService() ZiMaService {
return &zima{}
}
-func LoopNet() {
- netList := MyService.ZiMa().GetNetInfo()
+// func LoopNet() {
+// netList := MyService.ZiMa().GetNetInfo()
- nets := MyService.ZiMa().GetNet(true)
- num := 0
- for i := 0; i < len(netList); i++ {
+// nets := MyService.ZiMa().GetNet(true)
+// num := 0
+// for i := 0; i < len(netList); i++ {
- for _, netCardName := range nets {
+// for _, netCardName := range nets {
- if netList[i].Name == netCardName {
- var netArray []model.IOCountersStat
- if len(NetArray) < (num + 1) {
- netArray = []model.IOCountersStat{}
- } else {
- netArray = NetArray[num]
- }
- item := *(*model.IOCountersStat)(unsafe.Pointer(&netList[i]))
- item.State = strings.TrimSpace(MyService.ZiMa().GetNetState(netList[i].Name))
- item.Time = time.Now().Unix()
+// if netList[i].Name == netCardName {
+// var netArray []model.IOCountersStat
+// if len(NetArray) < (num + 1) {
+// netArray = []model.IOCountersStat{}
+// } else {
+// netArray = NetArray[num]
+// }
+// item := *(*model.IOCountersStat)(unsafe.Pointer(&netList[i]))
+// item.State = strings.TrimSpace(MyService.ZiMa().GetNetState(netList[i].Name))
+// item.Time = time.Now().Unix()
- if len(netArray) >= 60 {
- netArray = netArray[1:]
- }
- netArray = append(netArray, item)
- if len(NetArray) < (num + 1) {
- NetArray = append(NetArray, []model.IOCountersStat{})
- }
+// if len(netArray) >= 60 {
+// netArray = netArray[1:]
+// }
+// netArray = append(netArray, item)
+// if len(NetArray) < (num + 1) {
+// NetArray = append(NetArray, []model.IOCountersStat{})
+// }
- NetArray[num] = netArray
+// NetArray[num] = netArray
- num++
- break
- }
- }
+// num++
+// break
+// }
+// }
- }
-}
+// }
+// }
diff --git a/types/system.go b/types/system.go
index e3c7d0c..d6a3fae 100644
--- a/types/system.go
+++ b/types/system.go
@@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-02-17 18:53:22
* @LastEditors: LinkLeong
- * @LastEditTime: 2022-05-17 12:52:47
+ * @LastEditTime: 2022-06-01 18:05:37
* @FilePath: /CasaOS/types/system.go
* @Description:
* @Website: https://www.casaos.io
@@ -10,6 +10,6 @@
*/
package types
-const CURRENTVERSION = "0.3.1.1"
+const CURRENTVERSION = "0.3.2"
-const BODY = "
Fix the data loss problem when importing local applications"
+const BODY = ""
diff --git a/web/browserconfig.xml b/web/browserconfig.xml
index a02d62e..a221792 100644
--- a/web/browserconfig.xml
+++ b/web/browserconfig.xml
@@ -1,9 +1,9 @@
-
-
-
-
-
- #da532c
-
-
-
+
+
+
+
+
+ #da532c
+
+
+
diff --git a/web/favicon.svg b/web/favicon.svg
index 8d176f0..9760ab7 100644
--- a/web/favicon.svg
+++ b/web/favicon.svg
@@ -1,14 +1,14 @@
-
-
-
+
+
+
diff --git a/web/img/add_button.76237e85.svg b/web/img/add_button.07d47199.svg
similarity index 98%
rename from web/img/add_button.76237e85.svg
rename to web/img/add_button.07d47199.svg
index be6c60a..5618a52 100644
--- a/web/img/add_button.76237e85.svg
+++ b/web/img/add_button.07d47199.svg
@@ -1,11 +1,11 @@
-
+
diff --git a/web/img/android.149f5693.svg b/web/img/android.48a6cf16.svg
similarity index 98%
rename from web/img/android.149f5693.svg
rename to web/img/android.48a6cf16.svg
index 1c71253..2ad3eb1 100644
--- a/web/img/android.149f5693.svg
+++ b/web/img/android.48a6cf16.svg
@@ -1,25 +1,25 @@
-
-
-
-
+
+
+
+
diff --git a/web/img/application-x-apple.500bd1f9.svg b/web/img/application-x-apple.5eb295b2.svg
similarity index 98%
rename from web/img/application-x-apple.500bd1f9.svg
rename to web/img/application-x-apple.5eb295b2.svg
index 58022ef..d0b946b 100644
--- a/web/img/application-x-apple.500bd1f9.svg
+++ b/web/img/application-x-apple.5eb295b2.svg
@@ -1,28 +1,28 @@
-
-
-
+
+
+
diff --git a/web/img/casa-white.2579f069.svg b/web/img/casa-white.f250568a.svg
similarity index 98%
rename from web/img/casa-white.2579f069.svg
rename to web/img/casa-white.f250568a.svg
index 33a2f35..7cbc964 100644
--- a/web/img/casa-white.2579f069.svg
+++ b/web/img/casa-white.f250568a.svg
@@ -1,11 +1,11 @@
-
-
-
+
+
+
diff --git a/web/img/default-avatar.ab3b9bda.svg b/web/img/default-avatar.d92cd43a.svg
similarity index 98%
rename from web/img/default-avatar.ab3b9bda.svg
rename to web/img/default-avatar.d92cd43a.svg
index b217e0d..033868e 100644
--- a/web/img/default-avatar.ab3b9bda.svg
+++ b/web/img/default-avatar.d92cd43a.svg
@@ -1,39 +1,39 @@
-
-
-
+
+
+
diff --git a/web/img/folder-hdd.adcf549a.svg b/web/img/folder-hdd.42e0a4ee.svg
similarity index 98%
rename from web/img/folder-hdd.adcf549a.svg
rename to web/img/folder-hdd.42e0a4ee.svg
index c9fce2a..c90fc32 100644
--- a/web/img/folder-hdd.adcf549a.svg
+++ b/web/img/folder-hdd.42e0a4ee.svg
@@ -1,121 +1,121 @@
-
-
-
+
+
+
diff --git a/web/img/folder-usb.84d5b55d.svg b/web/img/folder-usb.1011b135.svg
similarity index 98%
rename from web/img/folder-usb.84d5b55d.svg
rename to web/img/folder-usb.1011b135.svg
index 253d168..4ef3d15 100644
--- a/web/img/folder-usb.84d5b55d.svg
+++ b/web/img/folder-usb.1011b135.svg
@@ -1,113 +1,113 @@
-
-
-
+
+
+
diff --git a/web/img/icon/safari-pinned-tab.svg b/web/img/icon/safari-pinned-tab.svg
index e750780..af12e15 100644
--- a/web/img/icon/safari-pinned-tab.svg
+++ b/web/img/icon/safari-pinned-tab.svg
@@ -1,25 +1,25 @@
-
-
-
+
+
+
diff --git a/web/img/macos.da8469ce.svg b/web/img/macos.6403eda3.svg
similarity index 97%
rename from web/img/macos.da8469ce.svg
rename to web/img/macos.6403eda3.svg
index 0d2f3ae..2645549 100644
--- a/web/img/macos.da8469ce.svg
+++ b/web/img/macos.6403eda3.svg
@@ -1,159 +1,159 @@
-
-