diff --git a/.gitignore b/.gitignore
index 0b33be0..62ef035 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,3 +37,4 @@ __debug_bin
main
CasaOS
github.com
+.all-contributorsrc
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d64918d..6704e1c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
+## [0.3.5-alpha] - 2022-08-08
+
+### Added
+
+- [File] Mount the shared samba
+- [File] File sharing via Samba
+- [System] You can share casaos on Twitter, facebook, reddit
+
+### Changed
+
+- [Disk] Support for mounting existing data disks
+
+### Fixed
+
+- [App] fixed uninstalling imported docker container apps results in wiping ALL your config data from them ([#360](https://github.com/IceWhaleTech/CasaOS/issues/360))
+
## [0.3.4] - 2022-07-29(UTC)
### Added
diff --git a/go.mod b/go.mod
index f329d17..c7a3e1f 100644
--- a/go.mod
+++ b/go.mod
@@ -6,7 +6,6 @@ require (
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d
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
@@ -22,17 +21,18 @@ require (
github.com/gin-contrib/gzip v0.0.2
github.com/gin-gonic/gin v1.7.2
github.com/go-ini/ini v1.62.0
- github.com/go-ole/go-ole v1.2.5 // indirect
github.com/go-playground/validator/v10 v10.6.1 // indirect
github.com/gogo/googleapis v1.4.1 // indirect
github.com/golang-jwt/jwt/v4 v4.4.1
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
+ github.com/golang/mock v1.6.0
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/hirochachacha/go-smb2 v1.1.0
github.com/jinzhu/copier v0.3.2
github.com/json-iterator/go v1.1.11 // indirect
github.com/klauspost/compress v1.13.6 // indirect
@@ -47,16 +47,17 @@ require (
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/opencontainers/selinux v1.8.5 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible
+ github.com/pilebones/go-udev v0.9.0
github.com/pkg/errors v0.9.1
github.com/prometheus/procfs v0.7.3 // indirect
github.com/robfig/cron v1.2.0
github.com/satori/go.uuid v1.2.0
- github.com/shirou/gopsutil/v3 v3.21.5
+ github.com/shirou/gopsutil/v3 v3.22.7
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/stretchr/testify v1.8.0
github.com/tidwall/gjson v1.10.2
- github.com/tklauser/go-sysconf v0.3.6 // indirect
github.com/ugorji/go v1.2.6 // indirect
go.opencensus.io v0.23.0 // indirect
go.uber.org/zap v1.10.0
@@ -64,7 +65,6 @@ require (
golang.org/x/mod v0.5.0 // indirect
golang.org/x/net v0.0.0-20211020060615-d418f374d309 // indirect
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
- golang.org/x/sys v0.0.0-20211020174200-9d6173849985 // indirect
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
@@ -75,7 +75,6 @@ require (
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0
- gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
gorm.io/driver/sqlite v1.2.6
gorm.io/gorm v1.22.5
)
diff --git a/go.sum b/go.sum
index f5c119c..202770e 100644
--- a/go.sum
+++ b/go.sum
@@ -86,9 +86,6 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
-github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
-github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 h1:5sXbqlSomvdjlRbWyNqkPsJ3Fg+tQZCbgeX1VGljbQY=
-github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -330,6 +327,8 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
+github.com/geoffgarside/ber v1.1.0 h1:qTmFG4jJbwiSzSXoNJeHcOprVzZ8Ulde2Rrrifu5U9w=
+github.com/geoffgarside/ber v1.1.0/go.mod h1:jVPKeCbj6MvQZhwLYsGwaGI52oUorHoHKNecGT85ZCc=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/gzip v0.0.2 h1:VMBkd4ZB1Hl7e1lOA5gEZ/qdD3d9vLIq57xKWgPCCV8=
@@ -356,9 +355,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
-github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
-github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
-github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
+github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
@@ -455,8 +453,9 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
+github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-github/v36 v36.0.0 h1:ndCzM616/oijwufI7nBRa+5eZHLldT+4yIB68ib5ogs=
@@ -513,6 +512,8 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/hirochachacha/go-smb2 v1.1.0 h1:b6hs9qKIql9eVXAiN0M2wSFY5xnhbHAQoCwRKbaRTZI=
+github.com/hirochachacha/go-smb2 v1.1.0/go.mod h1:8F1A4d5EZzrGu5R7PU163UcMRDJQl4FtcxjBfsY8TZE=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
@@ -577,6 +578,8 @@ github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/lucas-clemente/quic-go v0.25.0 h1:K+X9Gvd7JXsOHtU0N2icZ2Nw3rx82uBej3mP4CLgibc=
github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg=
+github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
+github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@@ -702,6 +705,8 @@ github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrap
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/pilebones/go-udev v0.9.0 h1:N1uEO/SxUwtIctc0WLU0t69JeBxIYEYnj8lT/Nabl9Q=
+github.com/pilebones/go-udev v0.9.0/go.mod h1:T2eI2tUSK0hA2WS5QLjXJUfQkluZQu+18Cqvem3CaXI=
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=
@@ -709,6 +714,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
+github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@@ -756,8 +763,8 @@ github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
-github.com/shirou/gopsutil/v3 v3.21.5 h1:YUBf0w/KPLk7w1803AYBnH7BmA+1Z/Q5MEZxpREUaB4=
-github.com/shirou/gopsutil/v3 v3.21.5/go.mod h1:ghfMypLDrFSWN2c9cDYFLHyynQ+QUht0cv/18ZqVczw=
+github.com/shirou/gopsutil/v3 v3.22.7 h1:flKnuCMfUUrO+oAvwAd6GKZgnPzr098VA/UJ14nhJd4=
+github.com/shirou/gopsutil/v3 v3.22.7/go.mod h1:s648gW4IywYzUfE/KjXxUsqrqx/T2xO5VqOXxONeRfI=
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
@@ -818,14 +825,17 @@ github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
@@ -837,12 +847,10 @@ github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
-github.com/tklauser/go-sysconf v0.3.4/go.mod h1:Cl2c8ZRWfHD5IrfHo9VN+FX9kCFjIOyVklgXycLB6ek=
-github.com/tklauser/go-sysconf v0.3.6 h1:oc1sJWvKkmvIxhDHeKWvZS4f6AW+YcoguSfRF2/Hmo4=
-github.com/tklauser/go-sysconf v0.3.6/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
-github.com/tklauser/numcpus v0.2.1/go.mod h1:9aU+wOc6WjUIZEwWMP62PL/41d65P+iks1gBkr4QyP8=
-github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA=
-github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM=
+github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
+github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
+github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
+github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
@@ -883,6 +891,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
+github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
@@ -1103,10 +1113,9 @@ golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210217105451-b926d437f341/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1116,8 +1125,9 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211020174200-9d6173849985 h1:LOlKVhfDyahgmqa97awczplwkjzNaELFg3zRIJ13RYo=
-golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -1340,8 +1350,8 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/sqlite v1.2.6 h1:SStaH/b+280M7C8vXeZLz/zo9cLQmIGwwj3cSj7p6l4=
gorm.io/driver/sqlite v1.2.6/go.mod h1:gyoX0vHiiwi0g49tv+x2E7l8ksauLK0U/gShcdUsjWY=
gorm.io/gorm v1.22.3/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
diff --git a/main.go b/main.go
index 932f28d..0aa2a70 100644
--- a/main.go
+++ b/main.go
@@ -15,6 +15,7 @@ import (
"github.com/IceWhaleTech/CasaOS/pkg/utils/random"
"github.com/IceWhaleTech/CasaOS/route"
"github.com/IceWhaleTech/CasaOS/service"
+ "github.com/IceWhaleTech/CasaOS/types"
"github.com/robfig/cron"
"gorm.io/gorm"
@@ -26,21 +27,31 @@ var configFlag = flag.String("c", "", "config address")
var dbFlag = flag.String("db", "", "db path")
var resetUser = flag.Bool("ru", false, "reset user")
var user = flag.String("user", "", "user name")
+var version = flag.Bool("v", false, "show version")
func init() {
flag.Parse()
+ if *version {
+ fmt.Println("v" + types.CURRENTVERSION)
+ return
+ }
config.InitSetup(*configFlag)
config.UpdateSetup()
+
loger.LogInit()
if len(*dbFlag) == 0 {
*dbFlag = config.AppInfo.DBPath + "/db"
}
+
sqliteDB = sqlite.GetDb(*dbFlag)
//gredis.GetRedisConn(config.RedisInfo),
+
service.MyService = service.NewService(sqliteDB)
+
service.Cache = cache.Init()
service.GetToken()
+
service.NewVersionApp = make(map[string]string)
route.InitFunction()
@@ -62,6 +73,9 @@ func init() {
// @BasePath /v1
func main() {
service.NotifyMsg = make(chan notify.Message, 10)
+ if *version {
+ return
+ }
if *resetUser {
if user == nil || len(*user) == 0 {
fmt.Println("user is empty")
@@ -81,7 +95,7 @@ func main() {
return
}
go route.SocketInit(service.NotifyMsg)
-
+ go route.MonitoryUSB()
//model.Setup()
//gredis.Setup()
r := route.InitRouter()
diff --git a/model/connections.go b/model/connections.go
new file mode 100644
index 0000000..84719ab
--- /dev/null
+++ b/model/connections.go
@@ -0,0 +1,20 @@
+/*
+ * @Author: LinkLeong link@icewhale.org
+ * @Date: 2022-07-27 10:30:43
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-08-04 20:06:04
+ * @FilePath: /CasaOS/model/connections.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+package model
+
+type Connections struct {
+ ID uint `json:"id"`
+ Username string `json:"username"`
+ Password string `json:"password,omitempty"`
+ Host string `json:"host"`
+ Port string `json:"port"`
+ MountPoint string `json:"mount_point"`
+}
diff --git a/model/disk.go b/model/disk.go
index dd48976..75d3bc5 100644
--- a/model/disk.go
+++ b/model/disk.go
@@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-07-13 10:43:45
* @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-13 11:00:04
+ * @LastEditTime: 2022-08-03 14:45:35
* @FilePath: /CasaOS/model/disk.go
* @Description:
* @Website: https://www.casaos.io
@@ -39,6 +39,7 @@ type LSBLKModel struct {
Serial string `json:"serial"`
Children []LSBLKModel `json:"children"`
SubSystems string `json:"subsystems"`
+ Label string `json:"label"`
//详情特有
StartSector uint64 `json:"start_sector,omitempty"`
Rota bool `json:"rota"` //true(hhd) false(ssd)
@@ -47,35 +48,46 @@ type LSBLKModel struct {
}
type Drive struct {
- Name string `json:"name"`
- Size uint64 `json:"size"`
- Model string `json:"model"`
- Health string `json:"health"`
- Temperature int `json:"temperature"`
- DiskType string `json:"disk_type"`
- NeedFormat bool `json:"need_format"`
- Serial string `json:"serial"`
- Path string `json:"path"`
+ Name string `json:"name"`
+ Size uint64 `json:"size"`
+ Model string `json:"model"`
+ Health string `json:"health"`
+ Temperature int `json:"temperature"`
+ DiskType string `json:"disk_type"`
+ NeedFormat bool `json:"need_format"`
+ Serial string `json:"serial"`
+ Path string `json:"path"`
+ ChildrenNumber int `json:"children_number"`
}
type DriveUSB struct {
- Name string `json:"name"`
- Size uint64 `json:"size"`
- Used uint64 `json:"use"`
- Model string `json:"model"`
- Mount bool `json:"mount"`
- Avail uint64 `json:"avail"`
+ Name string `json:"name"`
+ Size uint64 `json:"size"`
+ Model string `json:"model"`
+ Avail uint64 `json:"avail"`
+ Children []USBChildren `json:"children"`
+}
+type USBChildren struct {
+ Name string `json:"name"`
+ Size uint64 `json:"size"`
+ Avail uint64 `json:"avail"`
+ MountPoint string `json:"mount_point"`
}
type Storage struct {
- Name string `json:"name"`
- MountPoint string `json:"mountpoint"`
+ MountPoint string `json:"mount_point"`
Size string `json:"size"`
Avail string `json:"avail"` //可用空间
Type string `json:"type"`
- CreatedAt int64 `json:"create_at"`
Path string `json:"path"`
DriveName string `json:"drive_name"`
+ Label string `json:"label"`
+}
+type Storages struct {
+ DiskName string `json:"disk_name"`
+ Size uint64 `json:"size"`
+ Path string `json:"path"`
+ Children []Storage `json:"children"`
}
type Summary struct {
diff --git a/model/share.go b/model/share.go
new file mode 100644
index 0000000..f164db1
--- /dev/null
+++ b/model/share.go
@@ -0,0 +1,17 @@
+/*
+ * @Author: LinkLeong link@icewhale.org
+ * @Date: 2022-07-26 11:12:12
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-07-27 14:58:55
+ * @FilePath: /CasaOS/model/share.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+package model
+
+type Shares struct {
+ ID uint `json:"id"`
+ Anonymous bool `json:"anonymous"`
+ Path string `json:"path"`
+}
diff --git a/model/zima.go b/model/zima.go
index 217b3cc..e144b7c 100644
--- a/model/zima.go
+++ b/model/zima.go
@@ -1,14 +1,25 @@
+/*
+ * @Author: LinkLeong link@icewhale.org
+ * @Date: 2022-05-13 18:15:46
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-08-01 18:32:57
+ * @FilePath: /CasaOS/model/zima.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
package model
import "time"
type Path struct {
- Name string `json:"name"` //File name or document name
- Path string `json:"path"` //Full path to file or folder
- IsDir bool `json:"is_dir"` //Is it a folder
- Date time.Time `json:"date"`
- Size int64 `json:"size"` //File Size
- Type string `json:"type,omitempty"`
- Label string `json:"label,omitempty"`
- Write bool `json:"write"`
+ Name string `json:"name"` //File name or document name
+ Path string `json:"path"` //Full path to file or folder
+ IsDir bool `json:"is_dir"` //Is it a folder
+ Date time.Time `json:"date"`
+ Size int64 `json:"size"` //File Size
+ Type string `json:"type,omitempty"`
+ Label string `json:"label,omitempty"`
+ Write bool `json:"write"`
+ Extensions map[string]interface{} `json:"extensions"`
}
diff --git a/pkg/samba/smaba.go b/pkg/samba/smaba.go
new file mode 100644
index 0000000..58a9874
--- /dev/null
+++ b/pkg/samba/smaba.go
@@ -0,0 +1,75 @@
+/*
+ * @Author: LinkLeong link@icewhale.org
+ * @Date: 2022-07-27 10:35:29
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-08-01 13:56:44
+ * @FilePath: /CasaOS/pkg/samba/smaba.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+package samba
+
+import (
+ "errors"
+ "net"
+
+ "github.com/hirochachacha/go-smb2"
+)
+
+func ConnectSambaService(host, port, username, password, directory string) error {
+ conn, err := net.Dial("tcp", host+":"+port)
+ if err != nil {
+ return err
+ }
+ defer conn.Close()
+ d := &smb2.Dialer{
+ Initiator: &smb2.NTLMInitiator{
+ User: username,
+ Password: password,
+ },
+ }
+
+ s, err := d.Dial(conn)
+ if err != nil {
+ return err
+ }
+ defer s.Logoff()
+ names, err := s.ListSharenames()
+ if err != nil {
+ return err
+ }
+
+ for _, name := range names {
+ if name == directory {
+ return nil
+ }
+ }
+ return errors.New("directory not found")
+}
+
+//get share name list
+func GetSambaSharesList(host, port, username, password string) ([]string, error) {
+ conn, err := net.Dial("tcp", host+":"+port)
+ if err != nil {
+ return nil, err
+ }
+ defer conn.Close()
+ d := &smb2.Dialer{
+ Initiator: &smb2.NTLMInitiator{
+ User: username,
+ Password: password,
+ },
+ }
+
+ s, err := d.Dial(conn)
+ if err != nil {
+ return nil, err
+ }
+ defer s.Logoff()
+ names, err := s.ListSharenames()
+ if err != nil {
+ return nil, err
+ }
+ return names, err
+}
diff --git a/pkg/sqlite/db.go b/pkg/sqlite/db.go
index 3503cd0..383d2c4 100644
--- a/pkg/sqlite/db.go
+++ b/pkg/sqlite/db.go
@@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-13 18:15:46
* @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-11 18:10:53
+ * @LastEditTime: 2022-07-27 11:25:26
* @FilePath: /CasaOS/pkg/sqlite/db.go
* @Description:
* @Website: https://www.casaos.io
@@ -53,7 +53,7 @@ func GetDb(dbPath string) *gorm.DB {
drop table o_user;
`)
- err = db.AutoMigrate(&model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{}, model2.UserDBModel{})
+ err = db.AutoMigrate(&model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{}, model2.UserDBModel{}, model2.SharesDBModel{}, model2.ConnectionsDBModel{})
db.Exec("DROP TABLE IF EXISTS o_application")
db.Exec("DROP TABLE IF EXISTS o_friend")
db.Exec("DROP TABLE IF EXISTS o_person_download")
diff --git a/pkg/utils/common_err/e.go b/pkg/utils/common_err/e.go
index 79ee8cd..cc2a272 100644
--- a/pkg/utils/common_err/e.go
+++ b/pkg/utils/common_err/e.go
@@ -27,6 +27,9 @@ const (
PORT_IS_OCCUPIED = 20004
COMMAND_ERROR_INVALID_OPERATION = 20005
VERIFICATION_FAILURE = 20006
+ Record_NOT_EXIST = 20007
+ Record_ALREADY_EXIST = 20008
+ SERVICE_NOT_RUNNING = 20009
//disk
NAME_NOT_AVAILABLE = 40001
@@ -48,8 +51,9 @@ const (
DIR_NOT_EXISTS = 60004
SOURCE_DES_SAME = 60005
- //shortcuts
- SHORTCUTS_URL_ERROR = 70001
+ //share
+ SHARE_ALREADY_EXISTS = 70001
+ SHARE_NAME_ALREADY_EXISTS = 70002
)
var MsgFlags = map[int]string{
@@ -78,6 +82,9 @@ var MsgFlags = map[int]string{
FILE_OR_DIR_EXISTS: "File or folder already exists",
PORT_IS_OCCUPIED: "Port is occupied",
VERIFICATION_FAILURE: "Verification failure",
+ Record_ALREADY_EXIST: "Record already exists",
+ Record_NOT_EXIST: "Record does not exist",
+ SERVICE_NOT_RUNNING: "Service is not running",
//app
UNINSTALL_APP_ERROR: "Error uninstalling app",
@@ -91,16 +98,17 @@ var MsgFlags = map[int]string{
REMOVE_MOUNT_POINT_ERROR: "Failed to remove mount point",
DISK_BUSYING: "Drive is busy",
FORMAT_ERROR: "Formatting failed, please check if the directory is occupied",
-
+ //share
+ SHARE_ALREADY_EXISTS: "Share already exists",
+ SHARE_NAME_ALREADY_EXISTS: "Share name already exists",
//
SOURCE_DES_SAME: "Source and destination cannot be the same.",
FILE_DOES_NOT_EXIST: "File does not exist",
DIR_NOT_EXISTS: "Directory does not exist",
- FILE_READ_ERROR: "File read error",
- FILE_DELETE_ERROR: "Delete error",
- SHORTCUTS_URL_ERROR: "URL error",
+ FILE_READ_ERROR: "File read error",
+ FILE_DELETE_ERROR: "Delete error",
COMMAND_ERROR_INVALID_OPERATION: "invalid operation",
}
diff --git a/pkg/utils/file/file.go b/pkg/utils/file/file.go
index 20460ed..b08dcda 100644
--- a/pkg/utils/file/file.go
+++ b/pkg/utils/file/file.go
@@ -547,3 +547,20 @@ func MoveFile(sourcePath, destPath string) error {
}
return nil
}
+
+func ReadLine(lineNumber int, path string) string {
+ file, err := os.Open(path)
+ if err != nil {
+ return ""
+ }
+ fileScanner := bufio.NewScanner(file)
+ lineCount := 1
+ for fileScanner.Scan() {
+ if lineCount == lineNumber {
+ return fileScanner.Text()
+ }
+ lineCount++
+ }
+ defer file.Close()
+ return ""
+}
diff --git a/pkg/utils/udev_helper.go b/pkg/utils/udev_helper.go
new file mode 100644
index 0000000..701a6de
--- /dev/null
+++ b/pkg/utils/udev_helper.go
@@ -0,0 +1,33 @@
+/*
+ * @Author: LinkLeong link@icewhale.org
+ * @Date: 2022-08-10 16:06:12
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-08-10 16:11:37
+ * @FilePath: /CasaOS/pkg/utils/udev_helper.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+package utils
+
+// func getOptionnalMatcher() (matcher netlink.Matcher, err error) {
+// if filePath == nil || *filePath == "" {
+// return nil, nil
+// }
+
+// stream, err := ioutil.ReadFile(*filePath)
+// if err != nil {
+// return nil, err
+// }
+
+// if stream == nil {
+// return nil, fmt.Errorf("Empty, no rules provided in \"%s\", err: %w", *filePath, err)
+// }
+
+// var rules netlink.RuleDefinitions
+// if err := json.Unmarshal(stream, &rules); err != nil {
+// return nil, fmt.Errorf("Wrong rule syntax, err: %w", err)
+// }
+
+// return &rules, nil
+// }
diff --git a/route/darwin.go b/route/darwin.go
new file mode 100644
index 0000000..8e6dd35
--- /dev/null
+++ b/route/darwin.go
@@ -0,0 +1,25 @@
+//go:build darwin
+// +build darwin
+
+/*
+ * @Author: LinkLeong link@icewhale.org
+ * @Date: 2022-08-12 14:22:28
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-08-12 18:41:14
+ * @FilePath: /CasaOS/route/darwin.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+
+package route
+
+func MonitoryUSB() {
+
+}
+func SendAllHardwareStatusBySocket() {
+
+}
+func SendUSBBySocket() {
+
+}
diff --git a/route/init.go b/route/init.go
index 7aedb2f..19e4e20 100644
--- a/route/init.go
+++ b/route/init.go
@@ -1,11 +1,13 @@
package route
import (
+ "fmt"
"os"
"strconv"
"strings"
"github.com/IceWhaleTech/CasaOS/pkg/config"
+ "github.com/IceWhaleTech/CasaOS/pkg/samba"
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
@@ -15,15 +17,14 @@ import (
)
func InitFunction() {
-
ShellInit()
CheckSerialDiskMount()
-
CheckToken2_11()
ImportApplications()
+ // Soon to be removed
ChangeAPIUrl()
-
MoveUserToDB()
+ InitNetworkMount()
}
func CheckSerialDiskMount() {
@@ -40,25 +41,25 @@ func CheckSerialDiskMount() {
command.ExecEnabledSMART(v.Path)
if v.Children != nil {
for _, h := range v.Children {
- if len(h.MountPoint) == 0 && len(v.Children) == 1 && h.FsType == "ext4" {
- if m, ok := mountPoint[h.UUID]; ok {
- //mount point check
- volume := m
- if !file.CheckNotExist(m) {
- for i := 0; file.CheckNotExist(volume); i++ {
- volume = m + strconv.Itoa(i+1)
- }
+ //if len(h.MountPoint) == 0 && len(v.Children) == 1 && h.FsType == "ext4" {
+ if m, ok := mountPoint[h.UUID]; ok {
+ //mount point check
+ volume := m
+ if !file.CheckNotExist(m) {
+ for i := 0; file.CheckNotExist(volume); i++ {
+ volume = m + strconv.Itoa(i+1)
}
- service.MyService.Disk().MountDisk(h.Path, volume)
- if volume != m {
- ms := model2.SerialDisk{}
- ms.UUID = v.UUID
- ms.MountPoint = volume
- service.MyService.Disk().UpdateMountPoint(ms)
- }
-
}
+ service.MyService.Disk().MountDisk(h.Path, volume)
+ if volume != m {
+ ms := model2.SerialDisk{}
+ ms.UUID = v.UUID
+ ms.MountPoint = volume
+ service.MyService.Disk().UpdateMountPoint(ms)
+ }
+
}
+ //}
}
}
}
@@ -138,3 +139,32 @@ func MoveUserToDB() {
}
}
+
+func InitNetworkMount() {
+ connections := service.MyService.Connections().GetConnectionsList()
+ for _, v := range connections {
+ connection := service.MyService.Connections().GetConnectionByID(fmt.Sprint(v.ID))
+ directories, err := samba.GetSambaSharesList(connection.Host, connection.Port, connection.Username, connection.Password)
+ if err != nil {
+ service.MyService.Connections().DeleteConnection(fmt.Sprint(connection.ID))
+ continue
+ }
+ baseHostPath := "/mnt/" + connection.Host
+
+ mountPointList := service.MyService.System().GetDirPath(baseHostPath)
+ for _, v := range mountPointList {
+ service.MyService.Connections().UnmountSmaba(v.Path)
+ }
+
+ os.RemoveAll(baseHostPath)
+
+ file.IsNotExistMkDir(baseHostPath)
+ for _, v := range directories {
+ mountPoint := baseHostPath + "/" + v
+ file.IsNotExistMkDir(mountPoint)
+ service.MyService.Connections().MountSmaba(connection.Username, connection.Host, v, connection.Port, mountPoint, connection.Password)
+ }
+ connection.Directories = strings.Join(directories, ",")
+ service.MyService.Connections().UpdateConnection(&connection)
+ }
+}
diff --git a/route/periodical.go b/route/periodical.go
index 0740ab2..a4bcb10 100644
--- a/route/periodical.go
+++ b/route/periodical.go
@@ -1,8 +1,11 @@
+//go:build !darwin
+// +build !darwin
+
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-07-01 15:11:36
* @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-21 15:25:07
+ * @LastEditTime: 2022-08-12 18:58:00
* @FilePath: /CasaOS/route/periodical.go
* @Description:
* @Website: https://www.casaos.io
@@ -11,14 +14,20 @@
package route
import (
+ "os"
+ "os/signal"
"reflect"
"strconv"
"strings"
+ "syscall"
"time"
"unsafe"
"github.com/IceWhaleTech/CasaOS/model"
+ "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/IceWhaleTech/CasaOS/service"
+ "github.com/pilebones/go-udev/netlink"
+ "go.uber.org/zap"
)
func SendNetINfoBySocket() {
@@ -129,26 +138,22 @@ func SendUSBBySocket() {
usb := []model.DriveUSB{}
for _, v := range usbList {
if v.Tran == "usb" {
+ isMount := false
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 {
+ isMount = true
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)
+ if isMount {
+ usb = append(usb, temp)
+ }
}
}
service.MyService.Notify().SendUSBInfoBySocket(usb)
@@ -246,26 +251,22 @@ func SendAllHardwareStatusBySocket() {
usb := []model.DriveUSB{}
for _, v := range usbList {
if v.Tran == "usb" {
+ isMount = false
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 {
+ isMount = true
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)
+ if isMount {
+ usb = append(usb, temp)
+ }
+
}
}
memInfo := service.MyService.System().GetMemInfo()
@@ -273,3 +274,38 @@ func SendAllHardwareStatusBySocket() {
service.MyService.Notify().SendAllHardwareStatusBySocket(summary, usb, memInfo, cpuData, newNet)
}
+func MonitoryUSB() {
+ var matcher netlink.Matcher
+
+ conn := new(netlink.UEventConn)
+ if err := conn.Connect(netlink.UdevEvent); err != nil {
+ loger.Error("udev err", zap.Any("Unable to connect to Netlink Kobject UEvent socket", err))
+ }
+ defer conn.Close()
+
+ queue := make(chan netlink.UEvent)
+ errors := make(chan error)
+ quit := conn.Monitor(queue, errors, matcher)
+
+ signals := make(chan os.Signal, 1)
+ signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
+ go func() {
+ <-signals
+ close(quit)
+ os.Exit(0)
+ }()
+
+ for {
+ select {
+ case uevent := <-queue:
+ if uevent.Env["DEVTYPE"] == "disk" {
+ time.Sleep(time.Microsecond * 500)
+ SendUSBBySocket()
+ continue
+ }
+ case err := <-errors:
+ loger.Error("udev err", zap.Any("err", err))
+ }
+ }
+
+}
diff --git a/route/route.go b/route/route.go
index b6dd35a..b7a5cd6 100644
--- a/route/route.go
+++ b/route/route.go
@@ -196,6 +196,9 @@ func InitRouter() *gin.Engine {
//v1DisksGroup.POST("", v1.PostMountDisk)
v1DisksGroup.GET("", v1.GetDiskList)
+ v1DisksGroup.GET("/usb", v1.GetDisksUSBList)
+ v1DisksGroup.DELETE("/usb", v1.DeleteDiskUSB)
+ v1DisksGroup.DELETE("", v1.DeleteDisksUmount)
// //format storage
// v1DiskGroup.POST("/format", v1.PostDiskFormat)
@@ -218,6 +221,26 @@ func InitRouter() *gin.Engine {
v1StorageGroup.PUT("", v1.PostDiskFormat)
v1StorageGroup.DELETE("", v1.PostDiskUmount)
+ v1StorageGroup.GET("", v1.GetStorageList)
+ }
+ v1SambaGroup := v1Group.Group("/samba")
+ v1SambaGroup.Use()
+ {
+ v1ConnectionsGroup := v1SambaGroup.Group("/connections")
+ v1ConnectionsGroup.Use()
+ {
+ v1ConnectionsGroup.GET("", v1.GetSambaConnectionsList)
+ v1ConnectionsGroup.POST("", v1.PostSambaConnectionsCreate)
+ v1ConnectionsGroup.DELETE("/:id", v1.DeleteSambaConnections)
+ }
+ v1SharesGroup := v1SambaGroup.Group("/shares")
+ v1SharesGroup.Use()
+ {
+ v1SharesGroup.GET("", v1.GetSambaSharesList)
+ v1SharesGroup.POST("", v1.PostSambaSharesCreate)
+ v1SharesGroup.DELETE("/:id", v1.DeleteSambaShares)
+ v1SharesGroup.GET("/status", v1.GetSambaStatus)
+ }
}
}
return r
diff --git a/route/v1/disk.go b/route/v1/disk.go
index 9d19a16..f04a0b1 100644
--- a/route/v1/disk.go
+++ b/route/v1/disk.go
@@ -1,7 +1,6 @@
package v1
import (
- "fmt"
"net/http"
"reflect"
"strconv"
@@ -45,19 +44,12 @@ func GetDiskList(c *gin.Context) {
temp.Model = v.Model
temp.Name = v.Name
temp.Size = v.Size
- mountTemp := true
- if len(v.Children) == 0 {
- mountTemp = false
- }
for _, child := range v.Children {
if len(child.MountPoint) > 0 {
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
temp.Avail += avail
- } else {
- mountTemp = false
}
}
- temp.Mount = mountTemp
data = append(data, temp)
}
}
@@ -87,14 +79,13 @@ func GetDiskList(c *gin.Context) {
disk.Size = list[i].Size
disk.Path = list[i].Path
disk.Model = list[i].Model
-
+ disk.ChildrenNumber = len(list[i].Children)
if len(list[i].Children) > 0 && findSystem == 0 {
for j := 0; j < len(list[i].Children); j++ {
if len(list[i].Children[j].Children) > 0 {
for _, v := range list[i].Children[j].Children {
if v.MountPoint == "/" {
stor := model.Storage{}
- stor.Name = "System"
stor.MountPoint = v.MountPoint
stor.Size = v.FSSize
stor.Avail = v.FSAvail
@@ -118,7 +109,6 @@ func GetDiskList(c *gin.Context) {
} else {
if list[i].Children[j].MountPoint == "/" {
stor := model.Storage{}
- stor.Name = "System"
stor.MountPoint = list[i].Children[j].MountPoint
stor.Size = list[i].Children[j].FSSize
stor.Avail = list[i].Children[j].FSAvail
@@ -152,33 +142,31 @@ func GetDiskList(c *gin.Context) {
if reflect.DeepEqual(temp, model.SmartctlA{}) {
temp.SmartStatus.Passed = true
}
- if len(list[i].Children) == 1 && len(list[i].Children[0].MountPoint) > 0 {
- stor := model.Storage{}
- stor.MountPoint = list[i].Children[0].MountPoint
- stor.Size = list[i].Children[0].FSSize
- stor.Avail = list[i].Children[0].FSAvail
- stor.Path = list[i].Children[0].Path
- stor.Type = list[i].Children[0].FsType
- stor.DriveName = list[i].Name
- pathArr := strings.Split(list[i].Children[0].MountPoint, "/")
- if len(pathArr) == 3 {
- stor.Name = pathArr[2]
- }
- if t, ok := part[list[i].Children[0].MountPoint]; ok {
- stor.CreatedAt = t
- }
- storage = append(storage, stor)
- } else {
- //todo 长度有问题
- if len(list[i].Children) == 1 && list[i].Children[0].FsType == "ext4" {
- disk.NeedFormat = false
- avail = append(avail, disk)
- } else {
- disk.NeedFormat = true
- avail = append(avail, disk)
+ isAvail := true
+ for _, v := range list[i].Children {
+ if v.MountPoint != "" {
+ stor := model.Storage{}
+ stor.MountPoint = v.MountPoint
+ stor.Size = v.FSSize
+ stor.Avail = v.FSAvail
+ stor.Path = v.Path
+ stor.Type = v.FsType
+ stor.DriveName = list[i].Name
+ storage = append(storage, stor)
+ isAvail = false
}
}
+ if isAvail {
+ //if len(list[i].Children) == 1 && list[i].Children[0].FsType == "ext4" {
+ disk.NeedFormat = false
+ avail = append(avail, disk)
+ // } else {
+ // disk.NeedFormat = true
+ // avail = append(avail, disk)
+ // }
+ }
+
disk.Temperature = temp.Temperature.Current
disk.Health = strconv.FormatBool(temp.SmartStatus.Passed)
@@ -193,6 +181,107 @@ func GetDiskList(c *gin.Context) {
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
}
+// @Summary disk list
+// @Produce application/json
+// @Accept application/json
+// @Tags disk
+// @Security ApiKeyAuth
+// @Success 200 {string} string "ok"
+// @Router /disk/list [get]
+func GetDisksUSBList(c *gin.Context) {
+ list := service.MyService.Disk().LSBLK(false)
+ data := []model.DriveUSB{}
+ for _, v := range list {
+ if v.Tran == "usb" {
+ temp := model.DriveUSB{}
+ temp.Model = v.Model
+ temp.Name = v.Label
+ if temp.Name == "" {
+ temp.Name = v.Name
+ }
+ temp.Size = v.Size
+ children := []model.USBChildren{}
+ for _, child := range v.Children {
+
+ if len(child.MountPoint) > 0 {
+ tempChildren := model.USBChildren{}
+ tempChildren.MountPoint = child.MountPoint
+ tempChildren.Size, _ = strconv.ParseUint(child.FSSize, 10, 64)
+ tempChildren.Avail, _ = strconv.ParseUint(child.FSAvail, 10, 64)
+ tempChildren.Name = child.Label
+ avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
+ children = append(children, tempChildren)
+ temp.Avail += avail
+ }
+ }
+
+ temp.Children = children
+ data = append(data, temp)
+ }
+ }
+ c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
+
+}
+
+func DeleteDisksUmount(c *gin.Context) {
+ id := c.GetHeader("user_id")
+ js := make(map[string]string)
+ c.ShouldBind(&js)
+
+ path := js["path"]
+ pwd := js["password"]
+
+ if len(path) == 0 {
+ c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+ return
+ }
+ user := service.MyService.User().GetUserAllInfoById(id)
+ if user.Id == 0 {
+ c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
+ return
+ }
+ if encryption.GetMD5ByStr(pwd) != user.Password {
+ c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
+ return
+ }
+
+ if _, ok := diskMap[path]; ok {
+ c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
+ return
+ }
+
+ diskInfo := service.MyService.Disk().GetDiskInfo(path)
+ for _, v := range diskInfo.Children {
+ service.MyService.Disk().UmountPointAndRemoveDir(v.Path)
+ //delete data
+ service.MyService.Disk().DeleteMountPoint(v.Path, v.MountPoint)
+ }
+
+ service.MyService.Disk().RemoveLSBLKCache()
+
+ //send notify to client
+ msg := notify.StorageMessage{}
+ msg.Action = "REMOVED"
+ msg.Path = path
+ msg.Volume = ""
+ msg.Size = 0
+ msg.Type = ""
+ service.MyService.Notify().SendStorageBySocket(msg)
+ c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: path})
+}
+
+func DeleteDiskUSB(c *gin.Context) {
+ js := make(map[string]string)
+ c.ShouldBind(&js)
+ mountPoint := js["mount_point"]
+ if file.CheckNotExist(mountPoint) {
+ c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.DIR_NOT_EXISTS, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS)})
+ return
+ }
+ service.MyService.Disk().UmountUSB(mountPoint)
+ c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: mountPoint})
+}
+
// @Summary get disk list
// @Produce application/json
// @Accept application/json
@@ -278,10 +367,10 @@ func PostDiskAddPartition(c *gin.Context) {
js := make(map[string]interface{})
c.ShouldBind(&js)
path := js["path"].(string)
- name := js["name"].(string)
+ //name := js["name"].(string)
format := js["format"].(bool)
- if len(name) == 0 || len(path) == 0 {
+ if len(path) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
@@ -289,20 +378,17 @@ func PostDiskAddPartition(c *gin.Context) {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
return
}
- if !file.CheckNotExist("/DATA/" + name) {
- // /mnt/name exist
- c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NAME_NOT_AVAILABLE, Message: common_err.GetMsg(common_err.NAME_NOT_AVAILABLE)})
- return
- }
+
+ //diskInfo := service.MyService.Disk().GetDiskInfo(path)
+
+ // if !file.CheckNotExist("/DATA/" + name) {
+ // // /mnt/name exist
+ // c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NAME_NOT_AVAILABLE, Message: common_err.GetMsg(common_err.NAME_NOT_AVAILABLE)})
+ // return
+ // }
diskMap[path] = "busying"
currentDisk := service.MyService.Disk().GetDiskInfo(path)
- if !format {
- if len(currentDisk.Children) != 1 || !(len(currentDisk.Children) > 0 && currentDisk.Children[0].FsType == "ext4") {
- delete(diskMap, path)
- c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_NEEDS_FORMAT, Message: common_err.GetMsg(common_err.DISK_NEEDS_FORMAT)})
- return
- }
- } else {
+ if format {
// format := service.MyService.Disk().FormatDisk(path+"1", "ext4")
// if len(format) == 0 {
// delete(diskMap, path)
@@ -312,34 +398,45 @@ func PostDiskAddPartition(c *gin.Context) {
service.MyService.Disk().AddPartition(path)
}
- formatBool := true
- for formatBool {
- currentDisk = service.MyService.Disk().GetDiskInfo(path)
- fmt.Println(currentDisk.Children)
- if len(currentDisk.Children) > 0 {
- formatBool = false
- break
- }
- time.Sleep(time.Second)
- }
+ // formatBool := true
+ // for formatBool {
+ // currentDisk = service.MyService.Disk().GetDiskInfo(path)
+ // if len(currentDisk.Children) > 0 {
+ // formatBool = false
+ // break
+ // }
+ // time.Sleep(time.Second)
+ // }
currentDisk = service.MyService.Disk().GetDiskInfo(path)
- if len(currentDisk.Children) != 1 {
- c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_NEEDS_FORMAT, Message: common_err.GetMsg(common_err.DISK_NEEDS_FORMAT)})
- return
+ // if len(currentDisk.Children) != 1 {
+ // c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_NEEDS_FORMAT, Message: common_err.GetMsg(common_err.DISK_NEEDS_FORMAT)})
+ // return
+ // }
+ for i := 0; i < len(currentDisk.Children); i++ {
+ childrenName := currentDisk.Children[i].Label
+ if len(childrenName) == 0 {
+ childrenName = "Storage_" + currentDisk.Children[i].Name
+ }
+ mountPath := "/DATA/" + childrenName
+ if !file.CheckNotExist(mountPath) {
+ ls := service.MyService.System().GetDirPath(mountPath)
+ if len(ls) > 0 {
+ // exist
+ c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NAME_NOT_AVAILABLE, Message: common_err.GetMsg(common_err.NAME_NOT_AVAILABLE)})
+ return
+ }
+ }
+ m := model2.SerialDisk{}
+ m.MountPoint = mountPath
+ m.Path = currentDisk.Children[i].Path
+ m.UUID = currentDisk.Children[i].UUID
+ m.State = 0
+ m.CreatedAt = time.Now().Unix()
+ service.MyService.Disk().SaveMountPoint(m)
+ //mount dir
+ service.MyService.Disk().MountDisk(currentDisk.Children[i].Path, mountPath)
}
- mountPath := "/DATA/" + name
- m := model2.SerialDisk{}
- m.MountPoint = mountPath
- m.Path = currentDisk.Children[0].Path
- m.UUID = currentDisk.Children[0].UUID
- m.State = 0
- m.CreatedAt = time.Now().Unix()
- service.MyService.Disk().SaveMountPoint(m)
-
- //mount dir
- service.MyService.Disk().MountDisk(currentDisk.Children[0].Path, mountPath)
-
service.MyService.Disk().RemoveLSBLKCache()
delete(diskMap, path)
@@ -348,7 +445,7 @@ func PostDiskAddPartition(c *gin.Context) {
msg := notify.StorageMessage{}
msg.Action = "ADDED"
msg.Path = currentDisk.Children[0].Path
- msg.Volume = mountPath
+ msg.Volume = "/DATA/"
msg.Size = currentDisk.Children[0].Size
msg.Type = currentDisk.Children[0].Tran
service.MyService.Notify().SendStorageBySocket(msg)
diff --git a/route/v1/docker.go b/route/v1/docker.go
index 3e15ae1..c04cce8 100644
--- a/route/v1/docker.go
+++ b/route/v1/docker.go
@@ -209,7 +209,7 @@ func InstallApp(c *gin.Context) {
dockerImage = m.Image
dockerImageVersion = "latest"
}
-
+ m.Image = dockerImage + ":" + dockerImageVersion
for _, u := range m.Ports {
if u.Protocol == "udp" {
@@ -334,11 +334,11 @@ func InstallApp(c *gin.Context) {
return
}
- for !service.MyService.Docker().IsExistImage(dockerImage + ":" + dockerImageVersion) {
+ for !service.MyService.Docker().IsExistImage(m.Image) {
time.Sleep(time.Second)
}
- _, err = service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, m)
+ _, err = service.MyService.Docker().DockerContainerCreate(m, "")
if err != nil {
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100)
notify := notify.Application{}
@@ -829,7 +829,6 @@ func UpdateSetting(c *gin.Context) {
// c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR_APP_NAME_EXIST, Message: common_err.GetMsg(common_err.ERROR_APP_NAME_EXIST)})
// return
// }
-
service.MyService.Docker().DockerContainerStop(id)
portMap, _ := strconv.Atoi(m.PortMap)
if !port2.IsPortAvailable(portMap, "tcp") {
@@ -874,7 +873,7 @@ func UpdateSetting(c *gin.Context) {
service.MyService.Docker().DockerContainerUpdateName(id, id)
//service.MyService.Docker().DockerContainerRemove(id, true)
- containerId, err := service.MyService.Docker().DockerContainerCreate(m.Image, m)
+ containerId, err := service.MyService.Docker().DockerContainerCreate(m, id)
if err != nil {
service.MyService.Docker().DockerContainerUpdateName(m.ContainerName, id)
service.MyService.Docker().DockerContainerStart(id)
diff --git a/route/v1/file.go b/route/v1/file.go
index e2ca2b2..0b2dbc7 100644
--- a/route/v1/file.go
+++ b/route/v1/file.go
@@ -1,6 +1,7 @@
package v1
import (
+ "fmt"
"io"
"io/ioutil"
"log"
@@ -218,6 +219,11 @@ func GetDownloadSingleFile(c *gin.Context) {
func DirPath(c *gin.Context) {
path := c.DefaultQuery("path", "")
info := service.MyService.System().GetDirPath(path)
+ shares := service.MyService.Shares().GetSharesList()
+ sharesMap := make(map[string]string)
+ for _, v := range shares {
+ sharesMap[v.Path] = fmt.Sprint(v.ID)
+ }
if path == "/DATA/AppData" {
list := service.MyService.Docker().DockerContainerList()
apps := make(map[string]string, len(list))
@@ -257,7 +263,17 @@ func DirPath(c *gin.Context) {
}
}
}
+ for i := 0; i < len(info); i++ {
+ if v, ok := sharesMap[info[i].Path]; ok {
+ ex := make(map[string]interface{})
+ shareEx := make(map[string]string)
+ shareEx["shared"] = "true"
+ shareEx["id"] = v
+ ex["share"] = shareEx
+ info[i].Extensions = ex
+ }
+ }
//Hide the files or folders in operation
fileQueue := make(map[string]string)
if len(service.OpStrArr) > 0 {
diff --git a/route/v1/samba.go b/route/v1/samba.go
new file mode 100644
index 0000000..5bb3dc2
--- /dev/null
+++ b/route/v1/samba.go
@@ -0,0 +1,180 @@
+/*
+ * @Author: LinkLeong link@icewhale.com
+ * @Date: 2022-07-26 11:08:48
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-08-05 12:16:39
+ * @FilePath: /CasaOS/route/v1/samba.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+package v1
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/IceWhaleTech/CasaOS/model"
+ "github.com/IceWhaleTech/CasaOS/pkg/samba"
+ "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
+ "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
+ "github.com/IceWhaleTech/CasaOS/service"
+ model2 "github.com/IceWhaleTech/CasaOS/service/model"
+ "github.com/gin-gonic/gin"
+)
+
+// service
+
+func GetSambaStatus(c *gin.Context) {
+ status := service.MyService.System().IsServiceRunning("smbd")
+
+ if !status {
+ c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_NOT_RUNNING, Message: common_err.GetMsg(common_err.SERVICE_NOT_RUNNING)})
+ return
+ }
+ needInit := true
+ if file.Exists("/etc/samba/smb.conf") {
+ str := file.ReadLine(1, "/etc/samba/smb.conf")
+ if strings.Contains(str, "# Copyright (c) 2021-2022 CasaOS Inc. All rights reserved.") {
+ needInit = false
+ }
+ }
+ data := make(map[string]string, 1)
+ data["need_init"] = fmt.Sprintf("%v", needInit)
+ c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
+}
+
+func GetSambaSharesList(c *gin.Context) {
+ shares := service.MyService.Shares().GetSharesList()
+ shareList := []model.Shares{}
+ for _, v := range shares {
+ shareList = append(shareList, model.Shares{
+ Anonymous: v.Anonymous,
+ Path: v.Path,
+ ID: v.ID,
+ })
+ }
+ c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: shareList})
+}
+
+func PostSambaSharesCreate(c *gin.Context) {
+ shares := []model.Shares{}
+ c.ShouldBindJSON(&shares)
+ for _, v := range shares {
+ if v.Path == "" {
+ c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)})
+ return
+ }
+ if !file.Exists(v.Path) {
+ c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DIR_NOT_EXISTS, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS)})
+ return
+ }
+ if len(service.MyService.Shares().GetSharesByPath(v.Path)) > 0 {
+ c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.SHARE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.SHARE_ALREADY_EXISTS)})
+ return
+ }
+ if len(service.MyService.Shares().GetSharesByPath(filepath.Base(v.Path))) > 0 {
+ c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.SHARE_NAME_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.SHARE_NAME_ALREADY_EXISTS)})
+ return
+ }
+ }
+ for _, v := range shares {
+ shareDBModel := model2.SharesDBModel{}
+ shareDBModel.Anonymous = true
+ shareDBModel.Path = v.Path
+ shareDBModel.Name = filepath.Base(v.Path)
+ service.MyService.Shares().CreateShare(shareDBModel)
+ }
+
+ c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: shares})
+}
+func DeleteSambaShares(c *gin.Context) {
+ id := c.Param("id")
+ if id == "" {
+ c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)})
+ return
+ }
+ service.MyService.Shares().DeleteShare(id)
+ c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: id})
+}
+
+//client
+
+func GetSambaConnectionsList(c *gin.Context) {
+ connections := service.MyService.Connections().GetConnectionsList()
+ connectionList := []model.Connections{}
+ for _, v := range connections {
+ connectionList = append(connectionList, model.Connections{
+ ID: v.ID,
+ Username: v.Username,
+ Port: v.Port,
+ Host: v.Host,
+ MountPoint: v.MountPoint,
+ })
+ }
+ c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: connectionList})
+}
+
+func PostSambaConnectionsCreate(c *gin.Context) {
+ connection := model.Connections{}
+ c.ShouldBindJSON(&connection)
+ if connection.Port == "" {
+ connection.Port = "445"
+ }
+ if connection.Username == "" || connection.Host == "" {
+ c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
+ return
+ }
+ // check is exists
+
+ connections := service.MyService.Connections().GetConnectionByHost(connection.Host)
+ if len(connections) > 0 {
+ c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.Record_ALREADY_EXIST, Message: common_err.GetMsg(common_err.Record_ALREADY_EXIST), Data: common_err.GetMsg(common_err.Record_ALREADY_EXIST)})
+ return
+ }
+ // check connect is ok
+ directories, err := samba.GetSambaSharesList(connection.Host, connection.Port, connection.Username, connection.Password)
+ if err != nil {
+ c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
+ return
+ }
+
+ connectionDBModel := model2.ConnectionsDBModel{}
+ connectionDBModel.Username = connection.Username
+ connectionDBModel.Password = connection.Password
+ connectionDBModel.Host = connection.Host
+ connectionDBModel.Port = connection.Port
+ connectionDBModel.Directories = strings.Join(directories, ",")
+ baseHostPath := "/mnt/" + connection.Host
+ connectionDBModel.MountPoint = baseHostPath
+ connection.MountPoint = baseHostPath
+ file.IsNotExistMkDir(baseHostPath)
+ for _, v := range directories {
+ mountPoint := baseHostPath + "/" + v
+ file.IsNotExistMkDir(mountPoint)
+ service.MyService.Connections().MountSmaba(connectionDBModel.Username, connectionDBModel.Host, v, connectionDBModel.Port, mountPoint, connectionDBModel.Password)
+ }
+
+ service.MyService.Connections().CreateConnection(&connectionDBModel)
+
+ connection.ID = connectionDBModel.ID
+ c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: connection})
+}
+
+func DeleteSambaConnections(c *gin.Context) {
+ id := c.Param("id")
+ connection := service.MyService.Connections().GetConnectionByID(id)
+ if connection.Username == "" {
+ c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.Record_NOT_EXIST, Message: common_err.GetMsg(common_err.Record_NOT_EXIST)})
+ return
+ }
+ mountPointList := service.MyService.System().GetDirPath(connection.MountPoint)
+ for _, v := range mountPointList {
+ service.MyService.Connections().UnmountSmaba(v.Path)
+ }
+ os.RemoveAll(connection.MountPoint)
+ service.MyService.Connections().DeleteConnection(id)
+ c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: id})
+}
diff --git a/route/v1/samba_test.go b/route/v1/samba_test.go
new file mode 100644
index 0000000..455b973
--- /dev/null
+++ b/route/v1/samba_test.go
@@ -0,0 +1,73 @@
+/*
+ * @Author: LinkLeong link@icewhale.org
+ * @Date: 2022-08-02 15:10:56
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-08-02 16:58:42
+ * @FilePath: /CasaOS/route/v1/samba_test.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+package v1
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/gin-gonic/gin"
+ "github.com/golang/mock/gomock"
+ "github.com/stretchr/testify/assert"
+)
+
+func performRequest(r http.Handler, method, path string) *httptest.ResponseRecorder {
+ req, _ := http.NewRequest(method, path, nil)
+ w := httptest.NewRecorder()
+ r.ServeHTTP(w, req)
+ return w
+}
+
+// func TestHelloWorld(t *testing.T) {
+// // Build our expected body
+// body := gin.H{
+// "hello": "world",
+// }
+// // Grab our router
+// router := "SetupRouter()"
+// // Perform a GET request with that handler.
+// w := performRequest(router, "GET", "/")
+// // Assert we encoded correctly,
+// // the request gives a 200
+// assert.Equal(t, http.StatusOK, w.Code)
+// // Convert the JSON response to a map
+// var response map[string]string
+// err := json.Unmarshal([]byte(w.Body.String()), &response)
+// // Grab the value & whether or not it exists
+// value, exists := response["hello"]
+// // Make some assertions on the correctness of the response.
+// assert.Nil(t, err)
+// assert.True(t, exists)
+// assert.Equal(t, body["hello"], value)
+// }
+
+func TestGetSambaSharesList(t *testing.T) {
+ gin.SetMode(gin.TestMode)
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+ executeWithContext := func() *httptest.ResponseRecorder {
+ response := httptest.NewRecorder()
+ con, ginEngine := gin.CreateTestContext(response)
+
+ requestUrl := "/v1/samba/shares"
+ httpRequest, _ := http.NewRequest("GET", requestUrl, nil)
+ GetSambaSharesList(con)
+ ginEngine.ServeHTTP(response, httpRequest)
+ return response
+ }
+
+ t.Run("Happy", func(t *testing.T) {
+ res := executeWithContext()
+ assert.Equal(t, http.StatusOK, res.Code)
+ })
+
+}
diff --git a/route/v1/storage.go b/route/v1/storage.go
index ca02ed6..b45e22e 100644
--- a/route/v1/storage.go
+++ b/route/v1/storage.go
@@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-07-11 16:02:29
* @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-11 16:02:55
+ * @LastEditTime: 2022-08-11 14:20:02
* @FilePath: /CasaOS/route/v1/storage.go
* @Description:
* @Website: https://www.casaos.io
@@ -10,8 +10,95 @@
*/
package v1
-import "github.com/gin-gonic/gin"
+import (
+ "reflect"
+ "strconv"
+
+ "github.com/IceWhaleTech/CasaOS/model"
+ "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
+ "github.com/IceWhaleTech/CasaOS/service"
+ "github.com/gin-gonic/gin"
+)
func GetStorageList(c *gin.Context) {
+ system := c.Query("system")
+ storages := []model.Storages{}
+ disks := service.MyService.Disk().LSBLK(false)
+ diskNumber := 1
+ children := 1
+ findSystem := 0
+ for _, d := range disks {
+ if d.Tran != "usb" {
+ tempSystemDisk := false
+ children = 1
+ tempDisk := model.Storages{
+ DiskName: d.Model,
+ Path: d.Path,
+ Size: d.Size,
+ }
+ storageArr := []model.Storage{}
+ temp := service.MyService.Disk().SmartCTL(d.Path)
+ if reflect.DeepEqual(temp, model.SmartctlA{}) {
+ temp.SmartStatus.Passed = true
+ }
+ for _, v := range d.Children {
+ if v.MountPoint != "" {
+ if findSystem == 0 {
+ if v.MountPoint == "/" {
+ tempDisk.DiskName = "System"
+ findSystem = 1
+ tempSystemDisk = true
+ }
+ if len(v.Children) > 0 {
+ for _, c := range v.Children {
+ if c.MountPoint == "/" {
+ tempDisk.DiskName = "System"
+ findSystem = 1
+ tempSystemDisk = true
+ break
+ }
+ }
+ }
+ }
+
+ stor := model.Storage{}
+ stor.MountPoint = v.MountPoint
+ stor.Size = v.FSSize
+ stor.Avail = v.FSAvail
+ stor.Path = v.Path
+ stor.Type = v.FsType
+ stor.DriveName = v.Name
+ if len(v.Label) == 0 {
+ stor.Label = "Storage" + strconv.Itoa(diskNumber) + "_" + strconv.Itoa(children)
+ children += 1
+ } else {
+ stor.Label = v.Label
+ }
+ storageArr = append(storageArr, stor)
+ }
+ }
+
+ if len(storageArr) > 0 {
+ if tempSystemDisk && len(system) > 0 {
+ tempStorageArr := []model.Storage{}
+ for i := 0; i < len(storageArr); i++ {
+ if storageArr[i].MountPoint != "/boot/efi" && storageArr[i].Type != "swap" {
+ tempStorageArr = append(tempStorageArr, storageArr[i])
+ }
+ }
+ tempDisk.Children = tempStorageArr
+ storages = append(storages, tempDisk)
+ diskNumber += 1
+ } else if !tempSystemDisk {
+ tempDisk.Children = storageArr
+ storages = append(storages, tempDisk)
+ diskNumber += 1
+ }
+
+ }
+ }
+ }
+
+ c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: storages})
}
diff --git a/route/v1/system.go b/route/v1/system.go
index 42d7d32..e6d8029 100644
--- a/route/v1/system.go
+++ b/route/v1/system.go
@@ -174,7 +174,7 @@ func PostKillCasaOS(c *gin.Context) {
func PutSystemUSBAutoMount(c *gin.Context) {
js := make(map[string]string)
c.ShouldBind(&js)
- status := js["status"]
+ status := js["state"]
if status == "on" {
service.MyService.System().UpdateUSBAutoMount("True")
service.MyService.System().ExecUSBAutoMountShell("True")
@@ -182,7 +182,31 @@ func PutSystemUSBAutoMount(c *gin.Context) {
service.MyService.System().UpdateUSBAutoMount("False")
service.MyService.System().ExecUSBAutoMountShell("False")
}
+ go func() {
+ usbList := service.MyService.Disk().LSBLK(false)
+ usb := []model.DriveUSB{}
+ for _, v := range usbList {
+ if v.Tran == "usb" {
+ isMount := false
+ temp := model.DriveUSB{}
+ temp.Model = v.Model
+ temp.Name = v.Name
+ temp.Size = v.Size
+ for _, child := range v.Children {
+ if len(child.MountPoint) > 0 {
+ isMount = true
+ avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
+ temp.Avail += avail
+ }
+ }
+ if isMount {
+ usb = append(usb, temp)
+ }
+ }
+ }
+ service.MyService.Notify().SendUSBInfoBySocket(usb)
+ }()
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
@@ -202,7 +226,31 @@ func GetSystemUSBAutoMount(c *gin.Context) {
if config.ServerInfo.USBAutoMount == "False" {
state = "False"
}
+ go func() {
+ usbList := service.MyService.Disk().LSBLK(false)
+ usb := []model.DriveUSB{}
+ for _, v := range usbList {
+ if v.Tran == "usb" {
+ isMount := false
+ temp := model.DriveUSB{}
+ temp.Model = v.Model
+ temp.Name = v.Name
+ temp.Size = v.Size
+ for _, child := range v.Children {
+ if len(child.MountPoint) > 0 {
+ isMount = true
+ avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
+ temp.Avail += avail
+ }
+ }
+ if isMount {
+ usb = append(usb, temp)
+ }
+ }
+ }
+ service.MyService.Notify().SendUSBInfoBySocket(usb)
+ }()
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
@@ -354,21 +402,13 @@ func GetSystemUtilization(c *gin.Context) {
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)
}
}
diff --git a/service/connections.go b/service/connections.go
new file mode 100644
index 0000000..f9fe135
--- /dev/null
+++ b/service/connections.go
@@ -0,0 +1,69 @@
+/*
+ * @Author: LinkLeong link@icewhale.org
+ * @Date: 2022-07-26 18:13:22
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-08-04 20:10:31
+ * @FilePath: /CasaOS/service/connections.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+package service
+
+import (
+ "github.com/IceWhaleTech/CasaOS/pkg/config"
+ command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
+ "github.com/IceWhaleTech/CasaOS/service/model"
+ model2 "github.com/IceWhaleTech/CasaOS/service/model"
+ "gorm.io/gorm"
+)
+
+type ConnectionsService interface {
+ GetConnectionsList() (connections []model2.ConnectionsDBModel)
+ GetConnectionByHost(host string) (connections []model2.ConnectionsDBModel)
+ GetConnectionByID(id string) (connections model2.ConnectionsDBModel)
+ CreateConnection(connection *model2.ConnectionsDBModel)
+ DeleteConnection(id string)
+ UpdateConnection(connection *model2.ConnectionsDBModel)
+ MountSmaba(username, host, directory, port, mountPoint, password string) string
+ UnmountSmaba(mountPoint string) string
+}
+
+type connectionsStruct struct {
+ db *gorm.DB
+}
+
+func (s *connectionsStruct) GetConnectionByHost(host string) (connections []model2.ConnectionsDBModel) {
+ s.db.Select("username,host,status,id").Where("host = ?", host).Find(&connections)
+ return
+}
+func (s *connectionsStruct) GetConnectionByID(id string) (connections model2.ConnectionsDBModel) {
+ s.db.Select("username,password,host,status,id,directories,mount_point,port").Where("id = ?", id).First(&connections)
+ return
+}
+func (s *connectionsStruct) GetConnectionsList() (connections []model2.ConnectionsDBModel) {
+ s.db.Select("username,host,port,status,id,mount_point").Find(&connections)
+ return
+}
+func (s *connectionsStruct) CreateConnection(connection *model2.ConnectionsDBModel) {
+ s.db.Create(connection)
+}
+func (s *connectionsStruct) UpdateConnection(connection *model2.ConnectionsDBModel) {
+ s.db.Save(connection)
+}
+func (s *connectionsStruct) DeleteConnection(id string) {
+ s.db.Where("id= ?", id).Delete(&model.ConnectionsDBModel{})
+}
+
+func (s *connectionsStruct) MountSmaba(username, host, directory, port, mountPoint, password string) string {
+ str := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;MountCIFS " + username + " " + host + " " + directory + " " + port + " " + mountPoint + " " + password)
+ return str
+}
+func (s *connectionsStruct) UnmountSmaba(mountPoint string) string {
+ str := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;UMountPorintAndRemoveDir " + mountPoint)
+ return str
+}
+
+func NewConnectionsService(db *gorm.DB) ConnectionsService {
+ return &connectionsStruct{db: db}
+}
diff --git a/service/disk.go b/service/disk.go
index fb026bc..dfe8219 100644
--- a/service/disk.go
+++ b/service/disk.go
@@ -36,6 +36,7 @@ type DiskService interface {
DeleteMount(id string)
UpdateMountPoint(m model2.SerialDisk)
RemoveLSBLKCache()
+ UmountUSB(path string)
}
type diskService struct {
db *gorm.DB
@@ -45,6 +46,10 @@ func (d *diskService) RemoveLSBLKCache() {
key := "system_lsblk"
Cache.Delete(key)
}
+func (d *diskService) UmountUSB(path string) {
+ r := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;UDEVILUmount " + path)
+ fmt.Println(r)
+}
func (d *diskService) SmartCTL(path string) model.SmartctlA {
key := "system_smart_" + path
@@ -243,8 +248,9 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
}
func (d *diskService) MountDisk(path, volume string) {
+ //fmt.Println("source " + config.AppInfo.ShellPath + "/helper.sh ;do_mount " + path + " " + volume)
r := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;do_mount " + path + " " + volume)
- fmt.Print(r)
+ fmt.Println(r)
}
func (d *diskService) SaveMountPoint(m model2.SerialDisk) {
diff --git a/service/docker.go b/service/docker.go
index 4501345..45bc4a8 100644
--- a/service/docker.go
+++ b/service/docker.go
@@ -45,7 +45,7 @@ import (
type DockerService interface {
DockerPullImage(imageName string, icon, name string) error
IsExistImage(imageName string) bool
- DockerContainerCreate(imageName string, m model.CustomizationPostData) (containerId string, err error)
+ DockerContainerCreate(m model.CustomizationPostData, id string) (containerId string, err error)
DockerContainerCopyCreate(info *types.ContainerJSON) (containerId string, err error)
DockerContainerStart(name string) error
DockerContainerStats(name string) (string, error)
@@ -376,7 +376,7 @@ func (ds *dockerService) DockerContainerCopyCreate(info *types.ContainerJSON) (c
//param mapPort 容器主端口映射到外部的端口
//param tcp 容器其他tcp端口
//param udp 容器其他udp端口
-func (ds *dockerService) DockerContainerCreate(imageName string, m model.CustomizationPostData) (containerId string, err error) {
+func (ds *dockerService) DockerContainerCreate(m model.CustomizationPostData, id string) (containerId string, err error) {
if len(m.NetworkModel) == 0 {
m.NetworkModel = "bridge"
}
@@ -385,6 +385,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
if err != nil {
return "", err
}
+
defer cli.Close()
ports := make(nat.PortSet)
portMaps := make(nat.PortMap)
@@ -523,15 +524,26 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
if len(m.HostName) == 0 {
m.HostName = m.Label
}
- config := &container.Config{
- Image: imageName,
- Labels: map[string]string{"origin": m.Origin, m.Origin: m.Origin, "casaos": "casaos"},
- Env: envArr,
- // Healthcheck: health,
- Hostname: m.HostName,
- Cmd: m.Cmd,
+
+ info, err := cli.ContainerInspect(context.Background(), id)
+ hostConfig := &container.HostConfig{}
+ config := &container.Config{}
+ config.Labels = map[string]string{}
+ if err == nil {
+ // info.HostConfig = &container.HostConfig{}
+ // info.Config = &container.Config{}
+ // info.NetworkSettings = &types.NetworkSettings{}
+ hostConfig = info.HostConfig
+ config = info.Config
}
+ config.Cmd = m.Cmd
+ config.Image = m.Image
+ config.Env = envArr
+ config.Hostname = m.HostName
+ config.ExposedPorts = ports
+ config.Labels["origin"] = m.Origin
+ config.Labels["casaos"] = "casaos"
config.Labels["web"] = m.PortMap
config.Labels["icon"] = m.Icon
config.Labels["desc"] = m.Description
@@ -541,12 +553,19 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
config.Labels["protocol"] = m.Protocol
config.Labels["host"] = m.Host
config.Labels["name"] = m.Label
- hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: container.NetworkMode(m.NetworkModel), Privileged: m.Privileged, CapAdd: m.CapAdd}
+ //container, err := cli.ContainerCreate(context.Background(), info.Config, info.HostConfig, &network.NetworkingConfig{info.NetworkSettings.Networks}, nil, info.Name)
+
+ hostConfig.Mounts = volumes
+ hostConfig.Privileged = m.Privileged
+ hostConfig.CapAdd = m.CapAdd
+ hostConfig.NetworkMode = container.NetworkMode(m.NetworkModel)
+ hostConfig.RestartPolicy = rp
+ hostConfig.Resources = res
+ //hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: , Privileged: m.Privileged, CapAdd: m.CapAdd}
//if net != "host" {
- config.ExposedPorts = ports
+
hostConfig.PortBindings = portMaps
//}
-
containerDb, err := cli.ContainerCreate(context.Background(),
config,
hostConfig,
diff --git a/service/model/o_connections.go b/service/model/o_connections.go
new file mode 100644
index 0000000..45b1244
--- /dev/null
+++ b/service/model/o_connections.go
@@ -0,0 +1,28 @@
+/*
+ * @Author: LinkLeong link@icewhale.org
+ * @Date: 2022-07-26 17:17:57
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-08-01 17:08:08
+ * @FilePath: /CasaOS/service/model/o_connections.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+package model
+
+type ConnectionsDBModel struct {
+ ID uint `gorm:"column:id;primary_key" json:"id"`
+ Updated int64 `gorm:"autoUpdateTime"`
+ Created int64 `gorm:"autoCreateTime"`
+ Username string `json:"username"`
+ Password string `json:"password"`
+ Host string `json:"host"`
+ Port string `json:"port"`
+ Status string `json:"status"`
+ Directories string `json:"directories"` // string array
+ MountPoint string `json:"mount_point"` //parent directory of mount point
+}
+
+func (p *ConnectionsDBModel) TableName() string {
+ return "o_connections"
+}
diff --git a/service/model/o_shares.go b/service/model/o_shares.go
new file mode 100644
index 0000000..a887522
--- /dev/null
+++ b/service/model/o_shares.go
@@ -0,0 +1,24 @@
+/*
+ * @Author: LinkLeong link@icewhale.org
+ * @Date: 2022-07-26 11:17:17
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-07-27 15:25:07
+ * @FilePath: /CasaOS/service/model/o_shares.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+package model
+
+type SharesDBModel struct {
+ ID uint `gorm:"column:id;primary_key" json:"id"`
+ Anonymous bool `json:"anonymous"`
+ Path string `json:"path"`
+ Name string `json:"name"`
+ Updated int64 `gorm:"autoUpdateTime"`
+ Created int64 `gorm:"autoCreateTime"`
+}
+
+func (p *SharesDBModel) TableName() string {
+ return "o_shares"
+}
diff --git a/service/service.go b/service/service.go
index 2f348fc..9eac558 100644
--- a/service/service.go
+++ b/service/service.go
@@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-07-12 09:48:56
* @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-15 10:58:54
+ * @LastEditTime: 2022-07-27 10:28:48
* @FilePath: /CasaOS/service/service.go
* @Description:
* @Website: https://www.casaos.io
@@ -33,31 +33,44 @@ type Repository interface {
Notify() NotifyServer
Rely() RelyService
System() SystemService
+ Shares() SharesService
+ Connections() ConnectionsService
}
func NewService(db *gorm.DB) Repository {
return &store{
- app: NewAppService(db),
- user: NewUserService(db),
- docker: NewDockerService(),
- casa: NewCasaService(),
- disk: NewDiskService(db),
- notify: NewNotifyService(db),
- rely: NewRelyService(db),
- system: NewSystemService(),
+ app: NewAppService(db),
+ user: NewUserService(db),
+ docker: NewDockerService(),
+ casa: NewCasaService(),
+ disk: NewDiskService(db),
+ notify: NewNotifyService(db),
+ rely: NewRelyService(db),
+ system: NewSystemService(),
+ shares: NewSharesService(db),
+ connections: NewConnectionsService(db),
}
}
type store struct {
- db *gorm.DB
- app AppService
- user UserService
- docker DockerService
- casa CasaService
- disk DiskService
- notify NotifyServer
- rely RelyService
- system SystemService
+ db *gorm.DB
+ app AppService
+ user UserService
+ docker DockerService
+ casa CasaService
+ disk DiskService
+ notify NotifyServer
+ rely RelyService
+ system SystemService
+ shares SharesService
+ connections ConnectionsService
+}
+
+func (s *store) Connections() ConnectionsService {
+ return s.connections
+}
+func (s *store) Shares() SharesService {
+ return s.shares
}
func (c *store) Rely() RelyService {
diff --git a/service/shares.go b/service/shares.go
new file mode 100644
index 0000000..01ea7b0
--- /dev/null
+++ b/service/shares.go
@@ -0,0 +1,151 @@
+/*
+ * @Author: LinkLeong link@icewhale.org
+ * @Date: 2022-07-26 11:21:14
+ * @LastEditors: LinkLeong
+ * @LastEditTime: 2022-08-11 14:04:00
+ * @FilePath: /CasaOS/service/shares.go
+ * @Description:
+ * @Website: https://www.casaos.io
+ * Copyright (c) 2022 by icewhale, All Rights Reserved.
+ */
+package service
+
+import (
+ "path/filepath"
+ "strings"
+
+ "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/service/model"
+ model2 "github.com/IceWhaleTech/CasaOS/service/model"
+ "gorm.io/gorm"
+)
+
+type SharesService interface {
+ GetSharesList() (shares []model2.SharesDBModel)
+ GetSharesByPath(path string) (shares []model2.SharesDBModel)
+ GetSharesByName(name string) (shares []model2.SharesDBModel)
+ CreateShare(share model2.SharesDBModel)
+ DeleteShare(id string)
+ UpdateConfigFile()
+ InitSambaConfig()
+}
+
+type sharesStruct struct {
+ db *gorm.DB
+}
+
+func (s *sharesStruct) GetSharesByName(name string) (shares []model2.SharesDBModel) {
+ s.db.Select("anonymous,path,id").Where("name = ?", name).Find(&shares)
+
+ return
+}
+func (s *sharesStruct) GetSharesByPath(path string) (shares []model2.SharesDBModel) {
+ s.db.Select("anonymous,path,id").Where("path = ?", path).Find(&shares)
+ return
+}
+func (s *sharesStruct) GetSharesList() (shares []model2.SharesDBModel) {
+ s.db.Select("anonymous,path,id").Find(&shares)
+ return
+}
+func (s *sharesStruct) CreateShare(share model2.SharesDBModel) {
+ s.db.Create(&share)
+ s.InitSambaConfig()
+ s.UpdateConfigFile()
+}
+func (s *sharesStruct) DeleteShare(id string) {
+ s.db.Where("id= ?", id).Delete(&model.SharesDBModel{})
+ s.UpdateConfigFile()
+}
+
+func (s *sharesStruct) UpdateConfigFile() {
+ shares := []model2.SharesDBModel{}
+ s.db.Select("anonymous,path").Find(&shares)
+ //generated config file
+ var configStr = ""
+ for _, share := range shares {
+ dirName := filepath.Base(share.Path)
+ configStr += `
+[` + dirName + `]
+comment = CasaOS share ` + dirName + `
+public = Yes
+path = ` + share.Path + `
+browseable = Yes
+read only = No
+guest ok = Yes
+create mask = 0777
+directory mask = 0777
+
+`
+ }
+ //write config file
+ file.WriteToPath([]byte(configStr), "/etc/samba", "smb.casa.conf")
+ //restart samba
+ command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;RestartSMBD")
+
+}
+func (s *sharesStruct) InitSambaConfig() {
+ if file.Exists("/etc/samba/smb.conf") {
+ str := file.ReadLine(1, "/etc/samba/smb.conf")
+ if strings.Contains(str, "# Copyright (c) 2021-2022 CasaOS Inc. All rights reserved.") {
+ return
+ }
+ file.MoveFile("/etc/samba/smb.conf", "/etc/samba/smb.conf.bak")
+ var smbConf = ""
+ smbConf += `# Copyright (c) 2021-2022 CasaOS Inc. All rights reserved.
+#
+#
+# ______ _______
+# ( __ \ ( ___ )
+# | ( \ ) | ( ) |
+# | | ) | | | | |
+# | | | | | | | |
+# | | ) | | | | |
+# | (__/ ) | (___) |
+# (______/ (_______)
+#
+# _ _______ _________
+# ( ( /| ( ___ ) \__ __/
+# | \ ( | | ( ) | ) (
+# | \ | | | | | | | |
+# | (\ \) | | | | | | |
+# | | \ | | | | | | |
+# | ) \ | | (___) | | |
+# |/ )_) (_______) )_(
+#
+# _______ _______ ______ _________ _______
+# ( ) ( ___ ) ( __ \ \__ __/ ( ____ \ |\ /|
+# | () () | | ( ) | | ( \ ) ) ( | ( \/ ( \ / )
+# | || || | | | | | | | ) | | | | (__ \ (_) /
+# | |(_)| | | | | | | | | | | | | __) \ /
+# | | | | | | | | | | ) | | | | ( ) (
+# | ) ( | | (___) | | (__/ ) ___) (___ | ) | |
+# |/ \| (_______) (______/ \_______/ |/ \_/
+#
+#
+# IMPORTANT: CasaOS will not provide technical support for any issues
+# caused by unauthorized modification to the configuration.
+
+[global]
+## fruit settings
+ min protocol = SMB2
+ ea support = yes
+## vfs objects = fruit streams_xattr
+ fruit:metadata = stream
+ fruit:model = Macmini
+ fruit:veto_appledouble = no
+ fruit:posix_rename = yes
+ fruit:zero_file_id = yes
+ fruit:wipe_intentionally_left_blank_rfork = yes
+ fruit:delete_empty_adfiles = yes
+ map to guest = bad user
+ include=/etc/samba/smb.casa.conf`
+ file.WriteToPath([]byte(smbConf), "/etc/samba", "smb.conf")
+ }
+
+}
+
+func NewSharesService(db *gorm.DB) SharesService {
+ return &sharesStruct{db: db}
+}
diff --git a/service/system.go b/service/system.go
index 95ce9aa..1bb622f 100644
--- a/service/system.go
+++ b/service/system.go
@@ -49,6 +49,7 @@ type SystemService interface {
CreateFile(path string) (int, error)
RenameFile(oldF, newF string) (int, error)
MkdirAll(path string) (int, error)
+ IsServiceRunning(name string) bool
}
type systemService struct {
}
@@ -232,9 +233,9 @@ func (s *systemService) GetTimeZone() string {
func (s *systemService) ExecUSBAutoMountShell(state string) {
if state == "False" {
- command2.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;USB_Remove_File")
+ command2.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;USB_Stop_Auto")
} else {
- command2.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;USB_Move_File")
+ command2.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;USB_Start_Auto")
}
}
@@ -287,6 +288,12 @@ func GetDeviceAllIP() []string {
}
return address
}
+
+func (s *systemService) IsServiceRunning(name string) bool {
+ status := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;CheckServiceStatus smbd")
+ return strings.TrimSpace(status) == "running"
+
+}
func NewSystemService() SystemService {
return &systemService{}
}
diff --git a/shell/helper.sh b/shell/helper.sh
index 8bd81bf..a13b846 100644
--- a/shell/helper.sh
+++ b/shell/helper.sh
@@ -330,17 +330,17 @@ TarFolder() {
du -sh /DATA
}
-USB_Move_File() {
+USB_Start_Auto() {
((EUID)) && sudo_cmd="sudo"
- $sudo_cmd cp -rf /casaOS/server/shell/11-usb-mount.rules /etc/udev/rules.d/
- $sudo_cmd chmod +x /casaOS/server/shell/usb-mount.sh
- $sudo_cmd cp -rf /casaOS/server/shell/usb-mount@.service /etc/systemd/system/
+ $sudo_cmd systemctl enable devmon@devmon
+ $sudo_cmd systemctl start devmon@devmon
}
-USB_Remove_File() {
+USB_Stop_Auto() {
((EUID)) && sudo_cmd="sudo"
- $sudo_cmd rm -fr /etc/udev/rules.d/11-usb-mount.rules
- $sudo_cmd rm -fr /etc/systemd/system/usb-mount@.service
+ $sudo_cmd systemctl stop devmon@devmon
+ $sudo_cmd systemctl disable devmon@devmon
+ $sudo_cmd udevil clean
}
GetDeviceTree(){
@@ -363,4 +363,27 @@ AddSmabaUser(){
$2
$2
EOF
-}
\ No newline at end of file
+}
+
+# $1:username $2:host $3:share $4:port $5:mountpoint $6:password
+MountCIFS(){
+ $sudo_cmd mount -t cifs -o username=$1,password=$6,port=$4 //$2/$3 $5
+}
+
+# $1:service name
+CheckServiceStatus(){
+ rs="`systemctl status $1 |grep -E 'Active|PID'`"
+#echo "$rs"
+ run="`echo "$rs" |grep -B 2 'running'`"
+ fai="`echo "$rs" |grep -E -B 2 'failed|inactive|dead'`"
+ if [ "$run" == "" ]
+ then
+ echo "failed"
+ else
+ echo "running"
+ fi
+}
+UDEVILUmount(){
+ $sudo_cmd udevil umount -f $1
+}
+
diff --git a/types/system.go b/types/system.go
index 9a3d4e8..92b4c4c 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-07-18 18:47:15
+ * @LastEditTime: 2022-08-10 13:50:57
* @FilePath: /CasaOS/types/system.go
* @Description:
* @Website: https://www.casaos.io
@@ -10,6 +10,6 @@
*/
package types
-const CURRENTVERSION = "0.3.4"
+const CURRENTVERSION = "0.3.5"
-const BODY = ""
+const BODY = " "
diff --git a/web/index.html b/web/index.html
index bcede30..bb2b479 100644
--- a/web/index.html
+++ b/web/index.html
@@ -20,7 +20,7 @@
CasaOS
-
+