Compare commits

...

28 Commits

Author SHA1 Message Date
link
e7ebdc040f Merge pull request #48 from IceWhaleTech/dev
feat: Multiple updates
2021-12-09 19:03:45 +08:00
link
6c235d3f2a feat: Multiple updates
1.Add the function of modifying the WebUI port.
2.Add the function to modify the search engine.
3.Add the multi-language function and add Chinese translation.
4.Add detailed CPU and memory statistics.
2021-12-09 19:02:41 +08:00
link
997d912f4d Merge branch 'main' into dev 2021-12-06 17:12:53 +08:00
link
2508a4e07d Pull Submit 2021-12-06 17:08:36 +08:00
link
90b997337c Merge pull request #42 from xuchaoa/main
format code and fix wrong spell
2021-12-06 03:07:48 -06:00
xuc2
0bb3c92335 format code and fix wrong spell 2021-12-03 16:48:07 +08:00
link
7fd539c57e Merge pull request #40 from IceWhaleTech/dev
update volume path
2021-12-01 20:49:48 -06:00
link
52bd22ab2b update volume path 2021-12-02 10:49:02 +08:00
John Guan
46e9458e82 Update demo.yml 2021-12-01 21:58:57 +08:00
John Guan
3f5595e794 Update demo.yml 2021-12-01 21:54:02 +08:00
John Guan
d22cc7d3f6 Update demo.yml 2021-12-01 21:49:23 +08:00
John Guan
eb03a3e6c7 Update demo.yml 2021-12-01 21:46:34 +08:00
John Guan
65cc1f4752 Update demo.yml 2021-12-01 21:36:44 +08:00
John Guan
99db197a39 Update demo.yml 2021-12-01 21:31:17 +08:00
John Guan
7e2a5d553c Update demo.yml 2021-12-01 21:14:34 +08:00
John Guan
f02337b83b Update demo.yml 2021-12-01 21:09:18 +08:00
John Guan
f66b67b0c9 Update demo.yml 2021-12-01 21:05:52 +08:00
John Guan
91087b5341 Update demo.yml 2021-12-01 21:01:40 +08:00
John Guan
c67191d8c2 Update demo.yml 2021-12-01 20:45:36 +08:00
John Guan
0fac461783 Update demo.yml 2021-12-01 20:11:32 +08:00
John Guan
ec5bc922e7 Update demo.yml 2021-12-01 20:07:44 +08:00
John Guan
7194792c3f Update demo.yml 2021-12-01 19:51:36 +08:00
John Guan
76c8bade7f Update demo.yml 2021-12-01 19:50:30 +08:00
John Guan
126857fab0 Create demo.yml 2021-12-01 19:43:50 +08:00
link
9ca57e105e Merge pull request #38 from IceWhaleTech/dev
add uninstall.sh
2021-12-01 02:50:01 -06:00
link
2651140095 add uninstall.sh 2021-12-01 16:48:38 +08:00
link
14175bc438 Merge pull request #37 from IceWhaleTech/dev
fixed bug
2021-12-01 02:39:22 -06:00
link
956328da86 fixed bug 2021-12-01 16:25:56 +08:00
56 changed files with 978 additions and 378 deletions

79
.github/workflows/demo.yml vendored Normal file
View File

@@ -0,0 +1,79 @@
name: Demo Reset
# Controls when the workflow will run
on:
schedule:
- cron: "0 * * * *"
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# OLD_INSTANCE_SNAPSHOT_NAME=$(aws lightsail get-instance-snapshots | grep '"name": "CasaOS-Demo-Snapshot-[0-9]' | sed 's/ //g' | sed 's/"//g' | sed 's/,//g' | sed 's/name://g')
# OLD_INSTANCE_NAME=$(aws lightsail get-instances | grep '"name": "CasaOS-Demo-[0-9]' | sed 's/ //g' | sed 's/"//g' | sed 's/,//g' | sed 's/name://g')
# NEW_INSTANCE_NAME=CasaOS-Demo-$(date +%s)
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
reset:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
- name: Configure AWS credentials from Test account
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-west-2
- name: Get old instance and snapshot name, create new instance name
run: |
echo "OLD_INSTANCE_SNAPSHOT_NAME=$(aws lightsail get-instance-snapshots | grep '"name": "CasaOS-Demo-Snapshot-[0-9]' | sed 's/ //g' | sed 's/"//g' | sed 's/,//g' | sed 's/name://g')" >> $GITHUB_ENV
echo "OLD_INSTANCE_NAME=$(aws lightsail get-instances | grep '"name": "CasaOS-Demo-[0-9]' | sed 's/ //g' | sed 's/"//g' | sed 's/,//g' | sed 's/name://g')" >> $GITHUB_ENV
echo "NEW_INSTANCE_NAME=CasaOS-Demo-$(date +%s)" >> $GITHUB_ENV
- name: Create instances from snapshot
run: |
aws lightsail create-instances-from-snapshot \
--instance-snapshot-name ${{ env.OLD_INSTANCE_SNAPSHOT_NAME }} \
--instance-names ${{ env.NEW_INSTANCE_NAME }} \
--availability-zone us-west-2a \
--bundle-id large_2_0
- name: Wait for new instance running
run: |
TIMEOUT=$(($(date +%s)+600))
while [ $TIMEOUT -gt $(date +%s) ]
do
NEW_INSTANCE_STATE=$(aws lightsail get-instance-state --instance-name ${{ env.NEW_INSTANCE_NAME }} | grep '"name":' | sed 's/ //g' | sed 's/"//g' | sed 's/name://g')
if [ $NEW_INSTANCE_STATE == running ]
then
echo "New instance is running now"
sleep 10s
break
fi
done
- name: Put instance public ports
run: |
aws lightsail put-instance-public-ports \
--port-infos fromPort=0,toPort=65535,protocol=all \
--instance-name ${{ env.NEW_INSTANCE_NAME }}
- name: Attach static ip
run: |
aws lightsail attach-static-ip \
--static-ip-name CasaOS-Demo-IP \
--instance-name ${{ env.NEW_INSTANCE_NAME }}
- name: Delete old instance
run: |
aws lightsail delete-instance \
--instance-name ${{ env.OLD_INSTANCE_NAME }}

View File

@@ -35,6 +35,12 @@ or
curl -fsSL https://get.icewhale.io/casaos.sh | bash curl -fsSL https://get.icewhale.io/casaos.sh | bash
``` ```
### Uninstall CasaOS
```sh
curl -fsSL https://get.icewhale.io/casaos-uninstall.sh | bash
```
### System Compatibility ### System Compatibility
- Ubuntu Server 20.04 amd64 (✅ Recommend, Tested) - Ubuntu Server 20.04 amd64 (✅ Recommend, Tested)

2
UI

Submodule UI updated: a74be104eb...a982eb4bdd

4
go.mod
View File

@@ -48,8 +48,8 @@ require (
github.com/smartystreets/goconvey v1.6.4 // indirect github.com/smartystreets/goconvey v1.6.4 // indirect
github.com/swaggo/gin-swagger v1.3.0 github.com/swaggo/gin-swagger v1.3.0
github.com/swaggo/swag v1.7.3 github.com/swaggo/swag v1.7.3
github.com/tidwall/gjson v1.8.0 github.com/tidwall/gjson v1.10.2
github.com/tidwall/pretty v1.2.0 // indirect github.com/tidwall/sjson v1.2.3
github.com/tklauser/go-sysconf v0.3.6 // indirect github.com/tklauser/go-sysconf v0.3.6 // indirect
github.com/ugorji/go v1.2.6 // indirect github.com/ugorji/go v1.2.6 // indirect
go.opencensus.io v0.23.0 // indirect go.opencensus.io v0.23.0 // indirect

11
go.sum
View File

@@ -741,13 +741,14 @@ github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
github.com/tidwall/gjson v1.8.0 h1:Qt+orfosKn0rbNTZqHYDqBrmm3UDA4KRkv70fDzG+PQ= github.com/tidwall/gjson v1.10.2 h1:APbLGOM0rrEkd8WBw9C24nllro4ajFuJu0Sc9hRz8Bo=
github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.3 h1:5+deguEhHSEjmuICXZ21uSSsXotWMA0orU783+Z7Cp8=
github.com/tidwall/sjson v1.2.3/go.mod h1:5WdjKx3AQMvCJ4RG6/2UYT7dLrGvJUV1x4jdTAyGvZs=
github.com/tklauser/go-sysconf v0.3.4/go.mod h1:Cl2c8ZRWfHD5IrfHo9VN+FX9kCFjIOyVklgXycLB6ek= github.com/tklauser/go-sysconf v0.3.4/go.mod h1:Cl2c8ZRWfHD5IrfHo9VN+FX9kCFjIOyVklgXycLB6ek=
github.com/tklauser/go-sysconf v0.3.6 h1:oc1sJWvKkmvIxhDHeKWvZS4f6AW+YcoguSfRF2/Hmo4= github.com/tklauser/go-sysconf v0.3.6 h1:oc1sJWvKkmvIxhDHeKWvZS4f6AW+YcoguSfRF2/Hmo4=
github.com/tklauser/go-sysconf v0.3.6/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= github.com/tklauser/go-sysconf v0.3.6/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=

View File

@@ -2,8 +2,9 @@ package middleware
import ( import (
"fmt" "fmt"
"github.com/gin-gonic/gin"
"net/http" "net/http"
"github.com/gin-gonic/gin"
) )
func Cors() gin.HandlerFunc { func Cors() gin.HandlerFunc {
@@ -17,7 +18,7 @@ func Cors() gin.HandlerFunc {
//服务器支持的所有跨域请求的方法 //服务器支持的所有跨域请求的方法
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE") c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
//允许跨域设置可以返回其他子段,可以自定义字段 //允许跨域设置可以返回其他子段,可以自定义字段
c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session") c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,Language")
// 允许浏览器(客户端)可以解析的头部 (重要) // 允许浏览器(客户端)可以解析的头部 (重要)
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers") c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers")
//设置缓存时间 //设置缓存时间

View File

@@ -24,6 +24,7 @@ type LSBLKModel struct {
Tran string `json:"tran"` Tran string `json:"tran"`
MinIO uint64 `json:"min-io"` MinIO uint64 `json:"min-io"`
UsedPercent float64 `json:"used_percent"` UsedPercent float64 `json:"used_percent"`
Serial string `json:"serial"`
Children []LSBLKModel `json:"children"` Children []LSBLKModel `json:"children"`
//详情特有 //详情特有
StartSector uint64 `json:"start_sector,omitempty"` StartSector uint64 `json:"start_sector,omitempty"`

8
model/docker.go Normal file
View File

@@ -0,0 +1,8 @@
package model
type DockerStatsModel struct {
Icon string `json:"icon"`
Title string `json:"title"`
Data interface{} `json:"data"`
Pre interface{} `json:"pre"`
}

View File

@@ -20,9 +20,10 @@ type UserModel struct {
//服务配置 //服务配置
type ServerModel struct { type ServerModel struct {
HttpPort string HttpPort string
RunMode string RunMode string
ServerApi string ServerApi string
LockAccount bool
} }
//服务配置 //服务配置
@@ -67,3 +68,7 @@ type SystemConfig struct {
SyncPort string `json:"sync_port"` SyncPort string `json:"sync_port"`
SyncKey string `json:"sync_key"` SyncKey string `json:"sync_key"`
} }
type CasaOSGlobalVariables struct {
AddApp bool
}

View File

@@ -1,3 +1 @@
package model package model

View File

@@ -33,6 +33,8 @@ var ServerInfo = &model.ServerModel{}
var SystemConfigInfo = &model.SystemConfig{} var SystemConfigInfo = &model.SystemConfig{}
var CasaOSGlobalVariables = &model.CasaOSGlobalVariables{}
var Cfg *ini.File var Cfg *ini.File
//初始化设置,获取系统的部分信息。 //初始化设置,获取系统的部分信息。

View File

@@ -26,6 +26,8 @@ func GetDir(id, envName string) string {
path = "/DATA/Downloads/" path = "/DATA/Downloads/"
case strings.ToLower(envName) == "/srv": case strings.ToLower(envName) == "/srv":
path = "/DATA/" path = "/DATA/"
case strings.ToLower(envName) == "/tv":
path = "/DATA/Media/TV Shows"
default: default:
//path = "/media" //path = "/media"
} }

View File

@@ -6,7 +6,6 @@ import (
"golang.org/x/oauth2" "golang.org/x/oauth2"
) )
func GetGithubClient() *github.Client { func GetGithubClient() *github.Client {
ctx := context.Background() ctx := context.Background()
ts := oauth2.StaticTokenSource( ts := oauth2.StaticTokenSource(

View File

@@ -7,7 +7,7 @@ import (
"strings" "strings"
) )
func GetCtrlUrl(host,device string) string { func GetCtrlUrl(host, device string) string {
request := ctrlUrlRequest(host, device) request := ctrlUrlRequest(host, device)
response, _ := http.DefaultClient.Do(request) response, _ := http.DefaultClient.Do(request)
resultBody, _ := ioutil.ReadAll(response.Body) resultBody, _ := ioutil.ReadAll(response.Body)
@@ -86,4 +86,4 @@ func resolve(resultStr string) string {
} }
} }
return controlURL return controlURL
} }

View File

@@ -22,21 +22,21 @@ func send() (string, error) {
"ST: urn:schemas-upnp-org:service:WANIPConnection:1\r\n" + "ST: urn:schemas-upnp-org:service:WANIPConnection:1\r\n" +
"MAN: \"ssdp:discover\"\r\n" + "MX: 3\r\n\r\n" "MAN: \"ssdp:discover\"\r\n" + "MX: 3\r\n\r\n"
var conn *net.UDPConn var conn *net.UDPConn
remotAddr, err := net.ResolveUDPAddr("udp", "239.255.255.250:1900") remoteAddr, err := net.ResolveUDPAddr("udp", "239.255.255.250:1900")
if err != nil { if err != nil {
return "", errors.New("组播地址格式不正确") return "", errors.New("组播地址格式不正确")
} }
locaAddr, err := net.ResolveUDPAddr("udp", ip_helper2.GetLoclIp()+":") localAddr, err := net.ResolveUDPAddr("udp", ip_helper2.GetLoclIp()+":")
if err != nil { if err != nil {
return "", errors.New("本地ip地址格式不正确") return "", errors.New("本地ip地址格式不正确")
} }
conn, err = net.ListenUDP("udp", locaAddr) conn, err = net.ListenUDP("udp", localAddr)
defer conn.Close() defer conn.Close()
if err != nil { if err != nil {
return "", errors.New("监听udp出错") return "", errors.New("监听udp出错")
} }
_, err = conn.WriteToUDP([]byte(str), remotAddr) _, err = conn.WriteToUDP([]byte(str), remoteAddr)
if err != nil { if err != nil {
return "", errors.New("发送msg到组播地址出错") return "", errors.New("发送msg到组播地址出错")
} }

View File

@@ -5,4 +5,4 @@ import "testing"
func TestGateway(t *testing.T) { func TestGateway(t *testing.T) {
Gateway() Gateway()
} }

View File

@@ -2,40 +2,37 @@ package upnp
import ( import (
"bytes" "bytes"
"github.com/pkg/errors"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/pkg/errors"
) )
// //
////添加一个端口映射 ////添加一个端口映射
func (n *Upnp)AddPortMapping(localPort, remotePort int, protocol string) (err error) { func (n *Upnp) AddPortMapping(localPort, remotePort int, protocol string) (err error) {
defer func(err error) { defer func() {
if errTemp := recover(); errTemp != nil { if errTemp := recover(); errTemp != nil {
//log.Println("upnp模块报错了", errTemp) loger2.NewOLoger().Error("upnp模块报错了", errTemp)
err = errTemp.(error)
} }
}(err) }()
if issuccess := addSend(localPort, remotePort, protocol,n.GatewayHost, n.CtrlUrl,n.LocalHost); issuccess {
if isSuccess := addSend(localPort, remotePort, protocol, n.GatewayHost, n.CtrlUrl, n.LocalHost); isSuccess {
return nil return nil
} else { } else {
return errors.New("添加一个端口映射失败") return errors.New("添加一个端口映射失败")
} }
return
} }
func addSend(localPort, remotePort int, protocol, host, ctrUrl,localHost string) bool { func addSend(localPort, remotePort int, protocol, host, ctrUrl, localHost string) bool {
request := addRequest(localPort, remotePort, protocol, host, ctrUrl,localHost) request := addRequest(localPort, remotePort, protocol, host, ctrUrl, localHost)
response, _ := http.DefaultClient.Do(request) response, _ := http.DefaultClient.Do(request)
defer response.Body.Close() defer response.Body.Close()
//resultBody, _ := ioutil.ReadAll(response.Body) //resultBody, _ := ioutil.ReadAll(response.Body)
//fmt.Println(string(resultBody)) //fmt.Println(string(resultBody))
if response.StatusCode == 200 { return response.StatusCode == 200
return true
}
return false
} }
type Node struct { type Node struct {
@@ -45,7 +42,7 @@ type Node struct {
Child []Node Child []Node
} }
func addRequest(localPort, remotePort int, protocol string, gatewayHost, ctlUrl,localHost string) *http.Request { func addRequest(localPort, remotePort int, protocol string, gatewayHost, ctlUrl, localHost string) *http.Request {
//请求头 //请求头
header := http.Header{} header := http.Header{}
header.Set("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2") header.Set("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2")
@@ -109,27 +106,25 @@ func (n *Node) BuildXML() string {
return buf.String() return buf.String()
} }
func (n *Upnp)DelPortMapping(remotePort int, protocol string) bool { func (n *Upnp) DelPortMapping(remotePort int, protocol string) bool {
issuccess := delSendSend(remotePort, protocol,n.GatewayHost,n.CtrlUrl) isSuccess := delSendSend(remotePort, protocol, n.GatewayHost, n.CtrlUrl)
if issuccess { if isSuccess {
//this.MappingPort.delMapping(remotePort, protocol) //this.MappingPort.delMapping(remotePort, protocol)
//fmt.Println("删除了一个端口映射: remote:", remotePort) //fmt.Println("删除了一个端口映射: remote:", remotePort)
} }
return issuccess return isSuccess
} }
func delSendSend(remotePort int, protocol,host,ctlUrl string) bool { func delSendSend(remotePort int, protocol, host, ctlUrl string) bool {
delrequest := delbuildRequest(remotePort, protocol,host,ctlUrl) delrequest := delbuildRequest(remotePort, protocol, host, ctlUrl)
response, _ := http.DefaultClient.Do(delrequest) response, _ := http.DefaultClient.Do(delrequest)
//resultBody, _ := ioutil.ReadAll(response.Body) //resultBody, _ := ioutil.ReadAll(response.Body)
defer response.Body.Close() defer response.Body.Close()
if response.StatusCode == 200 {
// log.Println(string(resultBody)) return response.StatusCode == 200
return true
}
return false
} }
func delbuildRequest(remotePort int, protocol,host,ctlUrl string) *http.Request {
func delbuildRequest(remotePort int, protocol, host, ctlUrl string) *http.Request {
//请求头 //请求头
header := http.Header{} header := http.Header{}
header.Set("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2") header.Set("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2")
@@ -160,4 +155,4 @@ func delbuildRequest(remotePort int, protocol,host,ctlUrl string) *http.Request
request.Header = header request.Header = header
request.Header.Set("Content-Length", strconv.Itoa(len([]byte(bodyStr)))) request.Header.Set("Content-Length", strconv.Itoa(len([]byte(bodyStr))))
return request return request
} }

View File

@@ -7,10 +7,10 @@ import (
type Upnp struct { type Upnp struct {
LocalHost string `json:"local_host"` LocalHost string `json:"local_host"`
GatewayName string `json:"gateway_name"` //网关名称 GatewayName string `json:"gateway_name"` //网关名称
GatewayHost string `json:"gateway_host"` //网关ip和端口 GatewayHost string `json:"gateway_host"` //网关ip和端口
DeviceDescUrl string `json:"device_desc_url"` //设备描述url DeviceDescUrl string `json:"device_desc_url"` //设备描述url
CtrlUrl string `json:"ctrl_url"` //控制请求url CtrlUrl string `json:"ctrl_url"` //控制请求url
} }
func Testaaa() { func Testaaa() {
@@ -23,4 +23,3 @@ func Testaaa() {
fmt.Println("gateway ip address: ", upnpMan.Gateway.Host) fmt.Println("gateway ip address: ", upnpMan.Gateway.Host)
} }
} }

View File

@@ -6,4 +6,4 @@ import (
func TestTestaaa(t *testing.T) { func TestTestaaa(t *testing.T) {
(Testaaa()) (Testaaa())
} }

View File

@@ -6,7 +6,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
file2 "github.com/IceWhaleTech/CasaOS/pkg/utils/file" file2 "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
) )

View File

@@ -11,10 +11,12 @@ const (
PWD_IS_EMPTY = 10002 PWD_IS_EMPTY = 10002
PWD_INVALID_OLD = 10003 PWD_INVALID_OLD = 10003
ACCOUNT_LOCK = 10004
//system //system
DIR_ALREADY_EXISTS = 20001 DIR_ALREADY_EXISTS = 20001
FILE_ALREADY_EXISTS = 20002 FILE_ALREADY_EXISTS = 20002
FILE_OR_DIR_EXISTS = 20003 FILE_OR_DIR_EXISTS = 20003
PORT_IS_OCCUPIED = 20004
//zerotier //zerotier
GET_TOKEN_ERROR = 30001 GET_TOKEN_ERROR = 30001
@@ -42,11 +44,13 @@ var MsgFlags = map[int]string{
PWD_INVALID: "Password invalid", PWD_INVALID: "Password invalid",
PWD_IS_EMPTY: "Password is empty", PWD_IS_EMPTY: "Password is empty",
PWD_INVALID_OLD: "Old Password invalid", PWD_INVALID_OLD: "Old Password invalid",
ACCOUNT_LOCK: "Account Lock",
//system //system
DIR_ALREADY_EXISTS: "Directory already exists", DIR_ALREADY_EXISTS: "Directory already exists",
FILE_ALREADY_EXISTS: "File already exists", FILE_ALREADY_EXISTS: "File already exists",
FILE_OR_DIR_EXISTS: "File or directory already exists", FILE_OR_DIR_EXISTS: "File or directory already exists",
PORT_IS_OCCUPIED: "Port is occupied",
//zerotier //zerotier
GET_TOKEN_ERROR: "Get token error,Please log in to zerotier's official website to confirm whether the account is available", GET_TOKEN_ERROR: "Get token error,Please log in to zerotier's official website to confirm whether the account is available",

View File

@@ -6,5 +6,5 @@ import (
) )
func TestRandomString(t *testing.T) { func TestRandomString(t *testing.T) {
fmt.Println(RandomString(6,true)) fmt.Println(RandomString(6, true))
} }

View File

@@ -10,6 +10,7 @@ import (
"github.com/IceWhaleTech/CasaOS/model/system_app" "github.com/IceWhaleTech/CasaOS/model/system_app"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/docker" "github.com/IceWhaleTech/CasaOS/pkg/docker"
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper" "github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/port" "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
@@ -20,6 +21,7 @@ import (
func InitFunction() { func InitFunction() {
go checkSystemApp() go checkSystemApp()
Update2_3()
} }
var syncIsExistence = false var syncIsExistence = false
@@ -96,7 +98,7 @@ func installSyncthing(appId string) {
m.Origin = "system" m.Origin = "system"
m.PortMap = appInfo.PortMap m.PortMap = appInfo.PortMap
m.Ports = appInfo.Ports m.Ports = appInfo.Ports
m.Restart = "" m.Restart = "always"
m.Volumes = appInfo.Volumes m.Volumes = appInfo.Volumes
containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, id, m, appInfo.NetworkModel) containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, id, m, appInfo.NetworkModel)
@@ -156,6 +158,10 @@ func checkSystemApp() {
list := service.MyService.App().GetSystemAppList() list := service.MyService.App().GetSystemAppList()
for _, v := range *list { for _, v := range *list {
if v.Image == "linuxserver/syncthing" { if v.Image == "linuxserver/syncthing" {
if v.State != "running" {
//stepstart container
service.MyService.Docker().DockerContainerStart(v.CustomId)
}
syncIsExistence = true syncIsExistence = true
if config.SystemConfigInfo.SyncPort != v.Port { if config.SystemConfigInfo.SyncPort != v.Port {
config.SystemConfigInfo.SyncPort = v.Port config.SystemConfigInfo.SyncPort = v.Port
@@ -186,3 +192,10 @@ func checkSystemApp() {
installSyncthing("44") installSyncthing("44")
} }
} }
func CheckSerialDiskMount() {
// 检查挂载点重新挂载
// 检查新硬盘是否有多个分区,如有多个分区需提示
}
func Update2_3() {
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/assist.sh")
}

View File

@@ -12,6 +12,7 @@ import (
) )
var swagHandler gin.HandlerFunc var swagHandler gin.HandlerFunc
var OnlineDemo bool = false
func InitRouter() *gin.Engine { func InitRouter() *gin.Engine {
@@ -140,6 +141,8 @@ func InitRouter() *gin.Engine {
{ {
//获取我的已安装的列表 //获取我的已安装的列表
v1AppGroup.GET("/mylist", v1.MyAppList) v1AppGroup.GET("/mylist", v1.MyAppList)
//
v1AppGroup.GET("/usage", v1.AppUsageList)
//app详情 //app详情
v1AppGroup.GET("/appinfo/:id", v1.AppInfo) v1AppGroup.GET("/appinfo/:id", v1.AppInfo)
//获取未安装的列表 //获取未安装的列表
@@ -191,6 +194,9 @@ func InitRouter() *gin.Engine {
v1SysGroup.POST("/config", v1.PostSetSystemConfig) v1SysGroup.POST("/config", v1.PostSetSystemConfig)
v1SysGroup.GET("/widget/config", v1.GetWidgetConfig) v1SysGroup.GET("/widget/config", v1.GetWidgetConfig)
v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig) v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig)
v1SysGroup.GET("/port", v1.GetCasaOSPort)
v1SysGroup.PUT("/port", v1.PutCasaOSPort)
v1SysGroup.POST("/kill", v1.PostKillCasaOS)
} }
v1FileGroup := v1Group.Group("/file") v1FileGroup := v1Group.Group("/file")
v1FileGroup.Use() v1FileGroup.Use()
@@ -220,7 +226,7 @@ func InitRouter() *gin.Engine {
v1DiskGroup.POST("/format", v1.FormatDisk) v1DiskGroup.POST("/format", v1.FormatDisk)
//添加分区 //添加分区
v1DiskGroup.POST("/addpart", v1.AddPartition) v1DiskGroup.POST("/part", v1.AddPartition)
//获取可以格式化的内容 //获取可以格式化的内容
v1DiskGroup.GET("/type", v1.FormatDiskType) v1DiskGroup.GET("/type", v1.FormatDiskType)
@@ -228,6 +234,12 @@ func InitRouter() *gin.Engine {
//删除分区 //删除分区
v1DiskGroup.DELETE("/delpart", v1.RemovePartition) v1DiskGroup.DELETE("/delpart", v1.RemovePartition)
//mount SATA disk
v1DiskGroup.POST("/mount", v1.PostMountDisk)
//umount SATA disk
v1DiskGroup.POST("/umount", v1.DeleteUmountDisk)
} }
v1ShareGroup := v1Group.Group("/share") v1ShareGroup := v1Group.Group("/share")
v1ShareGroup.Use() v1ShareGroup.Use()

View File

@@ -103,6 +103,18 @@ func MyAppList(c *gin.Context) {
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list}) c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
} }
// @Summary my app hardware usage list
// @Produce application/json
// @Accept application/json
// @Tags app
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /app/usage [get]
func AppUsageList(c *gin.Context) {
list := service.MyService.App().GetHardwareUsage()
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
}
// @Summary 应用详情 // @Summary 应用详情
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
@@ -212,3 +224,14 @@ func ShareAppFile(c *gin.Context) {
content := service.MyService.OAPI().ShareAppFile(str) content := service.MyService.OAPI().ShareAppFile(str)
c.JSON(http.StatusOK, json.RawMessage(content)) c.JSON(http.StatusOK, json.RawMessage(content))
} }
// @Summary Resource Usage
// @Produce application/json
// @Accept application/json
// @Tags app
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /app/share [post]
func AppListResourceUsage() {
}

View File

@@ -64,7 +64,7 @@ func DDNSAddConfig(c *gin.Context) {
}) })
return return
} }
var m model2.DDNSUpdataDBModel var m model2.DDNSUpdateDBModel
c.Bind(&m) c.Bind(&m)
if err := service.MyService.DDNS().SaveConfig(m); err != nil { if err := service.MyService.DDNS().SaveConfig(m); err != nil {
c.JSON(http.StatusOK, c.JSON(http.StatusOK,

View File

@@ -1,13 +1,13 @@
package v1 package v1
import ( import (
"net/http"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err" "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/shirou/gopsutil/v3/disk" "github.com/shirou/gopsutil/v3/disk"
"net/http"
"strconv"
) )
// @Summary 获取磁盘列表 // @Summary 获取磁盘列表
@@ -59,7 +59,7 @@ func GetPlugInDisk(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: lst}) c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: lst})
} }
// @Summary 获取磁盘列表 // @Summary get disk list
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
// @Tags disk // @Tags disk
@@ -76,12 +76,12 @@ func GetPlugInDisks(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: result}) c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: result})
} }
// @Summary 磁盘详情 // @Summary disk detail
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
// @Tags disk // @Tags disk
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Param path query string true "要获取的磁盘详情 例如/dev/sda" // @Param path query string true "for example /dev/sda"
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /disk/info [get] // @Router /disk/info [get]
func GetDiskInfo(c *gin.Context) { func GetDiskInfo(c *gin.Context) {
@@ -93,7 +93,7 @@ func GetDiskInfo(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: m}) c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: m})
} }
// @Summary 磁盘详情 // @Summary format disk
// @Produce application/json // @Produce application/json
// @Accept multipart/form-data // @Accept multipart/form-data
// @Tags disk // @Tags disk
@@ -109,15 +109,9 @@ func FormatDisk(c *gin.Context) {
if len(path) == 0 || len(t) == 0 { if len(path) == 0 || len(t) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
} }
//删除挂载点
service.MyService.Disk().UmountPointAndRemoveDir(path)
//格式化磁盘 //格式化磁盘
service.MyService.Disk().FormatDisk(path, t) service.MyService.Disk().FormatDisk(path, t)
//重新挂载
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
} }
@@ -154,25 +148,43 @@ func RemovePartition(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
} }
// @Summary 添加分区 // @Summary serial number
// @Produce application/json // @Produce application/json
// @Accept multipart/form-data // @Accept multipart/form-data
// @Tags disk // @Tags disk
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Param path formData string true "磁盘路径 例如/dev/sda" // @Param path formData string true "磁盘路径 例如/dev/sda"
// @Param size formData string true "需要分区容量大小(MB)" // @Param serial formData string true "serial"
// @Param num formData string true "磁盘符号"
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /disk/addpart [post] // @Router /disk/addpart [post]
func AddPartition(c *gin.Context) { func AddPartition(c *gin.Context) {
path := c.PostForm("path") path := c.PostForm("path")
size, _ := strconv.Atoi(c.DefaultPostForm("size", "0")) serial := c.PostForm("serial")
num := c.DefaultPostForm("num", "9") if len(path) == 0 || len(serial) == 0 {
if len(path) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
return
} }
service.MyService.Disk().AddPartition(path)
//size*1024*1024/512 c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
service.MyService.Disk().AddPartition(path, num, uint64(size*1024*2)) }
func PostMountDisk(c *gin.Context) {
// for example: path=/dev/sda1
path := c.PostForm("path")
//执行挂载目录
service.MyService.Disk().MountDisk(path, "volume")
//添加到数据库
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
}
func DeleteUmountDisk(c *gin.Context) {
// for example: path=/dev/sda1
path := c.PostForm("path")
service.MyService.Disk().UmountPointAndRemoveDir(path)
//删除数据库记录
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
} }

View File

@@ -10,6 +10,7 @@ import (
"time" "time"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/docker" "github.com/IceWhaleTech/CasaOS/pkg/docker"
upnp2 "github.com/IceWhaleTech/CasaOS/pkg/upnp" upnp2 "github.com/IceWhaleTech/CasaOS/pkg/upnp"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
@@ -267,11 +268,11 @@ func InstallApp(c *gin.Context) {
rely.ContainerId = mysqlContainerId rely.ContainerId = mysqlContainerId
rely.CustomId = mid rely.CustomId = mid
rely.ContainerCustomId = id rely.ContainerCustomId = id
var msqlConfig model2.MysqlConfigs var mysqlConfig model2.MysqlConfigs
//结构体转换 //结构体转换
copier.Copy(&msqlConfig, &mc) copier.Copy(&mysqlConfig, &mc)
rely.Config = msqlConfig rely.Config = mysqlConfig
service.MyService.Rely().Create(rely) service.MyService.Rely().Create(rely)
relyMap["mysql"] = mid relyMap["mysql"] = mid
@@ -420,6 +421,12 @@ func InstallApp(c *gin.Context) {
rely := model.MapStrings{} rely := model.MapStrings{}
copier.Copy(&rely, &relyMap) copier.Copy(&rely, &relyMap)
if m.Origin != "custom" {
for i := 0; i < len(m.Volumes); i++ {
m.Volumes[i].Path = docker.GetDir(id, m.Volumes[i].ContainerPath)
}
}
portsStr, _ := json2.Marshal(m.Ports) portsStr, _ := json2.Marshal(m.Ports)
envsStr, _ := json2.Marshal(m.Envs) envsStr, _ := json2.Marshal(m.Envs)
volumesStr, _ := json2.Marshal(m.Volumes) volumesStr, _ := json2.Marshal(m.Volumes)
@@ -459,6 +466,7 @@ func InstallApp(c *gin.Context) {
// m.PortMap = m.Port // m.PortMap = m.Port
//} //}
service.MyService.App().SaveContainer(md) service.MyService.App().SaveContainer(md)
config.CasaOSGlobalVariables.AddApp = true
}() }()
@@ -673,7 +681,7 @@ func UnInstallApp(c *gin.Context) {
} }
//step删除容器 //step删除容器
err = service.MyService.Docker().DockerContainerRemove(appId) err = service.MyService.Docker().DockerContainerRemove(appId, false)
if err != nil { if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.UNINSTALL_APP_ERROR, Message: oasis_err2.GetMsg(oasis_err2.UNINSTALL_APP_ERROR), Data: err.Error()}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.UNINSTALL_APP_ERROR, Message: oasis_err2.GetMsg(oasis_err2.UNINSTALL_APP_ERROR), Data: err.Error()})
return return
@@ -924,7 +932,7 @@ func UpdateSetting(c *gin.Context) {
return return
} }
err = service.MyService.Docker().DockerContainerRemove(id) err = service.MyService.Docker().DockerContainerRemove(id, true)
if err != nil { if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
return return

View File

@@ -4,12 +4,14 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"os"
"strconv" "strconv"
"time" "time"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err" "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
"github.com/IceWhaleTech/CasaOS/pkg/utils/version" "github.com/IceWhaleTech/CasaOS/pkg/utils/version"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model" model2 "github.com/IceWhaleTech/CasaOS/service/model"
@@ -80,7 +82,7 @@ func GetCasaOSErrorLogs(c *gin.Context) {
// @Produce application/json // @Produce application/json
// @Accept multipart/form-data // @Accept multipart/form-data
// @Tags sys // @Tags sys
// @Param file formData file true "用户头像" // @Param config formData string true "config json string"
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /sys/changhead [post] // @Router /sys/changhead [post]
@@ -102,7 +104,7 @@ func GetSystemConfigDebug(c *gin.Context) {
array := service.MyService.System().GetSystemConfigDebug() array := service.MyService.System().GetSystemConfigDebug()
disk := service.MyService.ZiMa().GetDiskInfo() disk := service.MyService.ZiMa().GetDiskInfo()
array = append(array, fmt.Sprintf("disk,totle:%v,used:%v,UsedPercent:%v", disk.Total>>20, disk.Used>>20, disk.UsedPercent)) array = append(array, fmt.Sprintf("disk,total:%v,used:%v,UsedPercent:%v", disk.Total>>20, disk.Used>>20, disk.UsedPercent))
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: array}) c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: array})
} }
@@ -135,6 +137,58 @@ func PostSetWidgetConfig(c *gin.Context) {
}) })
} }
// @Summary get casaos server port
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/port [get]
func GetCasaOSPort(c *gin.Context) {
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err.SUCCESS,
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
Data: config.ServerInfo.HttpPort,
})
}
// @Summary edit casaos server port
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Param port formData string true "port"
// @Success 200 {string} string "ok"
// @Router /sys/port [put]
func PutCasaOSPort(c *gin.Context) {
port, err := strconv.Atoi(c.PostForm("port"))
if err != nil {
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err.ERROR,
Message: err.Error(),
})
return
}
isAvailable := port2.IsPortAvailable(port, "tcp")
if !isAvailable {
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err.PORT_IS_OCCUPIED,
Message: oasis_err.GetMsg(oasis_err.PORT_IS_OCCUPIED),
})
return
}
service.MyService.System().UpSystemPort(strconv.Itoa(port))
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err.SUCCESS,
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
})
}
// @Summary 检查是否进入引导状态 // @Summary 检查是否进入引导状态
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
@@ -156,3 +210,14 @@ func GetGuideCheck(c *gin.Context) {
Data: data, Data: data,
}) })
} }
// @Summary active killing casaos
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/kill [post]
func PostKillCasaOS(c *gin.Context) {
os.Exit(0)
}

View File

@@ -123,6 +123,10 @@ func Up_Load_Head(c *gin.Context) {
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /user/changusername [put] // @Router /user/changusername [put]
func Chang_User_Name(c *gin.Context) { func Chang_User_Name(c *gin.Context) {
if config.ServerInfo.LockAccount {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ACCOUNT_LOCK, Message: oasis_err2.GetMsg(oasis_err2.ACCOUNT_LOCK)})
return
}
oldname := c.PostForm("oldname") oldname := c.PostForm("oldname")
username := c.PostForm("username") username := c.PostForm("username")
if len(username) == 0 || config.UserInfo.UserName != oldname { if len(username) == 0 || config.UserInfo.UserName != oldname {
@@ -149,6 +153,10 @@ func Chang_User_Pwd(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PWD_INVALID_OLD, Message: oasis_err2.GetMsg(oasis_err2.PWD_INVALID_OLD)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PWD_INVALID_OLD, Message: oasis_err2.GetMsg(oasis_err2.PWD_INVALID_OLD)})
return return
} }
if config.ServerInfo.LockAccount {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ACCOUNT_LOCK, Message: oasis_err2.GetMsg(oasis_err2.ACCOUNT_LOCK)})
return
}
if len(pwd) == 0 { if len(pwd) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PWD_IS_EMPTY, Message: oasis_err2.GetMsg(oasis_err2.PWD_IS_EMPTY)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PWD_IS_EMPTY, Message: oasis_err2.GetMsg(oasis_err2.PWD_IS_EMPTY)})
return return

View File

@@ -2,9 +2,15 @@ package service
import ( import (
"context" "context"
"encoding/json"
"io"
"io/ioutil"
"runtime"
"strings" "strings"
"sync"
"time" "time"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/command" "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
@@ -27,6 +33,9 @@ type AppService interface {
GetSimpleContainerInfo(name string) (types.Container, error) GetSimpleContainerInfo(name string) (types.Container, error)
DelAppConfigDir(path string) DelAppConfigDir(path string)
GetSystemAppList() *[]model2.MyAppList GetSystemAppList() *[]model2.MyAppList
GetHardwareUsageSteam()
GetHardwareUsage() []model.DockerStatsModel
GetAppStats(id string) string
} }
type appStruct struct { type appStruct struct {
@@ -48,7 +57,6 @@ func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppLis
if err != nil { if err != nil {
a.log.Error("获取docker容器失败", "app.getmylist", "line:42", err) a.log.Error("获取docker容器失败", "app.getmylist", "line:42", err)
} }
//获取本地数据库应用 //获取本地数据库应用
var lm []model2.AppListDBModel var lm []model2.AppListDBModel
@@ -68,8 +76,7 @@ func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppLis
for _, container := range containers { for _, container := range containers {
if lMap[container.ID] != nil && container.Labels["origin"] != "system" { if lMap[container.ID] != nil && container.Labels["origin"] != "system" {
var m model2.AppListDBModel m := lMap[container.ID].(model2.AppListDBModel)
m = lMap[container.ID].(model2.AppListDBModel)
if len(m.Label) == 0 { if len(m.Label) == 0 {
m.Label = m.Title m.Label = m.Title
} }
@@ -129,8 +136,7 @@ func (a *appStruct) GetSystemAppList() *[]model2.MyAppList {
for _, container := range containers { for _, container := range containers {
if lMap[container.ID] != nil { if lMap[container.ID] != nil {
var m model2.AppListDBModel m := lMap[container.ID].(model2.AppListDBModel)
m = lMap[container.ID].(model2.AppListDBModel)
if len(m.Label) == 0 { if len(m.Label) == 0 {
m.Label = m.Title m.Label = m.Title
} }
@@ -156,7 +162,6 @@ func (a *appStruct) GetSystemAppList() *[]model2.MyAppList {
//Rely: m.Rely, //Rely: m.Rely,
}) })
} }
} }
return &list return &list
@@ -194,6 +199,10 @@ func (a *appStruct) GetSimpleContainerInfo(name string) (types.Container, error)
filters := filters.NewArgs() filters := filters.NewArgs()
filters.Add("name", name) filters.Add("name", name)
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters}) containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters})
if err != nil {
return types.Container{}, err
}
if len(containers) > 0 { if len(containers) > 0 {
return containers[0], nil return containers[0], nil
} }
@@ -231,6 +240,110 @@ func (a *appStruct) RemoveContainerById(id string) {
a.db.Table(model2.CONTAINERTABLENAME).Where("custom_id = ?", id).Delete(&model2.AppListDBModel{}) a.db.Table(model2.CONTAINERTABLENAME).Where("custom_id = ?", id).Delete(&model2.AppListDBModel{})
} }
var dataStr map[string]model.DockerStatsModel
var isFinish bool = false
func (a *appStruct) GetAppStats(id string) string {
cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil {
return ""
}
defer cli.Close()
con, err := cli.ContainerStats(context.Background(), id, false)
if err != nil {
return err.Error()
}
defer con.Body.Close()
c, _ := ioutil.ReadAll(con.Body)
return string(c)
}
func (a *appStruct) GetHardwareUsage() []model.DockerStatsModel {
steam := true
for !isFinish {
if steam {
steam = false
go func() {
a.GetHardwareUsageSteam()
}()
}
// 切一下,再次分配任务
runtime.Gosched()
}
list := []model.DockerStatsModel{}
for _, v := range dataStr {
list = append(list, v)
}
return list
}
func (a *appStruct) GetHardwareUsageSteam() {
var lock = &sync.Mutex{}
if len(dataStr) == 0 {
lock.Lock()
dataStr = make(map[string]model.DockerStatsModel)
lock.Unlock()
}
cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil {
return
}
defer cli.Close()
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
var lm []model2.AppListDBModel
a.db.Table(model2.CONTAINERTABLENAME).Select("label,icon,container_id").Where("origin != ?", "system").Find(&lm)
var list []types.ContainerStats
for i := 0; i < 100; i++ {
if config.CasaOSGlobalVariables.AddApp {
a.db.Table(model2.CONTAINERTABLENAME).Select("label,icon,container_id").Where("origin != ?", "system").Find(&lm)
}
var wg sync.WaitGroup
for _, v := range lm {
wg.Add(1)
go func(v model2.AppListDBModel, lock *sync.Mutex) {
defer wg.Done()
stats, err := cli.ContainerStats(ctx, v.ContainerId, true)
if err != nil {
return
}
decode := json.NewDecoder(stats.Body)
var data interface{}
if err := decode.Decode(&data); err == io.EOF {
return
}
lock.Lock()
dockerStats := model.DockerStatsModel{}
dockerStats.Pre = dataStr[v.ContainerId].Data
dockerStats.Data = data
dockerStats.Icon = v.Icon
dockerStats.Title = v.Label
dataStr[v.ContainerId] = dockerStats
lock.Unlock()
}(v, lock)
}
wg.Wait()
isFinish = true
if i == 99 {
for _, v := range list {
v.Body.Close()
}
}
time.Sleep(time.Second * 2)
}
isFinish = false
cancel()
}
// init install // init install
func Init() { func Init() {

View File

@@ -1,12 +1,13 @@
package service package service
import ( import (
"os/exec"
ip_helper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper" ip_helper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/IceWhaleTech/CasaOS/service/ddns" "github.com/IceWhaleTech/CasaOS/service/ddns"
"github.com/IceWhaleTech/CasaOS/service/model" "github.com/IceWhaleTech/CasaOS/service/model"
"gorm.io/gorm" "gorm.io/gorm"
"os/exec"
) )
type ddnsStruct struct { type ddnsStruct struct {
@@ -20,17 +21,15 @@ type DDNSService interface {
GetConfigList() *[]model.DDNSList GetConfigList() *[]model.DDNSList
DeleteConfig(id uint) bool DeleteConfig(id uint) bool
GetType(name string) (uint, string) GetType(name string) (uint, string)
SaveConfig(model model.DDNSUpdataDBModel) error SaveConfig(model model.DDNSUpdateDBModel) error
} }
//判断当前添加的是否存在 //判断当前添加的是否存在
func (d *ddnsStruct) IsExis(t int, domain string, host string) bool { func (d *ddnsStruct) IsExis(t int, domain string, host string) bool {
var count int64 var count int64
d.db.Table(model.DDNSLISTTABLENAME).Where("type=? AND domain=? AND host=?", t, domain, host).Count(&count) d.db.Table(model.DDNSLISTTABLENAME).Where("type=? AND domain=? AND host=?", t, domain, host).Count(&count)
if count > 0 {
return true return count > 0
}
return false
} }
//前台获取已配置的ddns列表 //前台获取已配置的ddns列表
@@ -41,7 +40,7 @@ func (d *ddnsStruct) GetConfigList() *[]model.DDNSList {
} }
func (d *ddnsStruct) DeleteConfig(id uint) bool { func (d *ddnsStruct) DeleteConfig(id uint) bool {
d.db.Delete(&model.DDNSUpdataDBModel{Id: id}) d.db.Delete(&model.DDNSUpdateDBModel{Id: id})
return true return true
} }
@@ -66,12 +65,12 @@ func (d *ddnsStruct) GetType(name string) (uint, string) {
} }
//保存配置到数据库 //保存配置到数据库
func (d *ddnsStruct) GetDockerRootDir(model model.DDNSUpdataDBModel) error { func (d *ddnsStruct) GetDockerRootDir(model model.DDNSUpdateDBModel) error {
return d.db.Create(&model).Error return d.db.Create(&model).Error
} }
//保存配置到数据库 //保存配置到数据库
func (d *ddnsStruct) SaveConfig(model model.DDNSUpdataDBModel) error { func (d *ddnsStruct) SaveConfig(model model.DDNSUpdateDBModel) error {
return d.db.Create(&model).Error return d.db.Create(&model).Error
} }
@@ -87,7 +86,7 @@ func chackPing(b chan bool, url string) {
} }
//更新列表 //更新列表
func UpdataDDNSList(db *gorm.DB) { func UpdateDDNSList(db *gorm.DB) {
var s []model.DDNSCoreList var s []model.DDNSCoreList
db.Table(model.DDNSLISTTABLENAME).Select("o_ddns_type.name as name,o_ddns_type.api_host as api_host,o_ddns.id,`host`,domain,user_name,`password`,`key`,secret,type").Joins("left join o_ddns_type on o_ddns.type=o_ddns_type.id").Scan(&s) db.Table(model.DDNSLISTTABLENAME).Select("o_ddns_type.name as name,o_ddns_type.api_host as api_host,o_ddns.id,`host`,domain,user_name,`password`,`key`,secret,type").Joins("left join o_ddns_type on o_ddns.type=o_ddns_type.id").Scan(&s)
for _, item := range s { for _, item := range s {

View File

@@ -31,4 +31,3 @@ func SetOauth(request *http.Request, value string) {
func SetXFilter(request *http.Request, value string) { func SetXFilter(request *http.Request, value string) {
request.Header.Set("X-Filter", value) request.Header.Set("X-Filter", value)
} }

View File

@@ -10,8 +10,10 @@ import (
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command" command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/shirou/gopsutil/v3/disk" "github.com/shirou/gopsutil/v3/disk"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"gorm.io/gorm"
) )
type DiskService interface { type DiskService interface {
@@ -21,11 +23,14 @@ type DiskService interface {
UmountPointAndRemoveDir(path string) string UmountPointAndRemoveDir(path string) string
GetDiskInfo(path string) model.LSBLKModel GetDiskInfo(path string) model.LSBLKModel
DelPartition(path, num string) string DelPartition(path, num string) string
AddPartition(path, num string, size uint64) string AddPartition(path string) string
GetDiskInfoByPath(path string) *disk.UsageStat GetDiskInfoByPath(path string) *disk.UsageStat
MountDisk(path, volume string)
SerialAll(mountPoint string) *[]model2.SerialDisk
} }
type diskService struct { type diskService struct {
log loger2.OLog log loger2.OLog
db *gorm.DB
} }
//通过脚本获取外挂磁盘 //通过脚本获取外挂磁盘
@@ -55,28 +60,17 @@ func (d *diskService) DelPartition(path, num string) string {
return "" return ""
} }
//添加分区 //part
func (d *diskService) AddPartition(path, num string, size uint64) string { func (d *diskService) AddPartition(path string) string {
r := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;AddPartition " + path)
var maxSector uint64 = 0
chiList := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetPartitionSectors " + path)
if len(chiList) == 0 {
d.log.Error("chiList length error")
}
for i := 0; i < len(chiList); i++ {
tempArr := strings.Split(chiList[i], ",")
tempSector, _ := strconv.ParseUint(tempArr[2], 10, 64)
if tempSector > maxSector {
maxSector = tempSector
}
}
r := command2.ExecResultStrArray("source ./shell/helper.sh ;AddPartition " + path + " " + num + " " + strconv.FormatUint(maxSector+1, 10) + " " + strconv.FormatUint(size+maxSector+1, 10))
fmt.Println(r) fmt.Println(r)
return "" return ""
} }
func (d *diskService) AddAllPartition(path string) {
}
//获取硬盘详情 //获取硬盘详情
func (d *diskService) GetDiskInfoByPath(path string) *disk.UsageStat { func (d *diskService) GetDiskInfoByPath(path string) *disk.UsageStat {
diskInfo, err := disk.Usage(path + "1") diskInfo, err := disk.Usage(path + "1")
@@ -90,7 +84,7 @@ func (d *diskService) GetDiskInfoByPath(path string) *disk.UsageStat {
return diskInfo return diskInfo
} }
//获取磁盘信息 //get disk details
func (d *diskService) LSBLK() []model.LSBLKModel { func (d *diskService) LSBLK() []model.LSBLKModel {
str := command2.ExecLSBLK() str := command2.ExecLSBLK()
if str == nil { if str == nil {
@@ -111,7 +105,7 @@ func (d *diskService) LSBLK() []model.LSBLKModel {
var health = true var health = true
for _, i := range m { for _, i := range m {
if i.Children != nil { if i.Type != "loop" && !i.RO {
fsused = 0 fsused = 0
for _, child := range i.Children { for _, child := range i.Children {
if child.RM { if child.RM {
@@ -134,7 +128,7 @@ func (d *diskService) LSBLK() []model.LSBLKModel {
i.Children = c i.Children = c
if fsused > 0 { if fsused > 0 {
i.UsedPercent, err = strconv.ParseFloat(fmt.Sprintf("%.4f", float64(fsused)/float64(i.Size)), 64) i.UsedPercent, err = strconv.ParseFloat(fmt.Sprintf("%.4f", float64(fsused)/float64(i.Size)), 64)
fmt.Println(err) d.log.Fatal("diskservice_lsblk_fsused", err)
} }
n = append(n, i) n = append(n, i)
health = true health = true
@@ -197,17 +191,21 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
return m return m
} }
//func GetDiskInfo(path string) *disk.UsageStat { func (d *diskService) MountDisk(path, volume string) {
// diskInfo, _ := disk.Usage(path) r := command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;do_mount " + path + " " + volume)
// diskInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.UsedPercent), 64) fmt.Print(r)
// diskInfo.InodesUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.InodesUsedPercent), 64) }
// return diskInfo
//} func (d *diskService) SaveMountPoint(m model2.SerialDisk) {
d.db.Save(&m)
//func (d *diskService) GetPlugInDisk() []string { }
// return disk.Partitions(false)
//} func (d *diskService) SerialAll(mountPoint string) *[]model2.SerialDisk {
var m []model2.SerialDisk
func NewDiskService(log loger2.OLog) DiskService { d.db.Find(&m)
return &diskService{log: log} return &m
}
func NewDiskService(log loger2.OLog, db *gorm.DB) DiskService {
return &diskService{log: log, db: db}
} }

View File

@@ -53,7 +53,7 @@ type DockerService interface {
DockerListByImage(image, version string) (*types.Container, error) DockerListByImage(image, version string) (*types.Container, error)
DockerContainerInfo(name string) (*types.ContainerJSON, error) DockerContainerInfo(name string) (*types.ContainerJSON, error)
DockerImageRemove(name string) error DockerImageRemove(name string) error
DockerContainerRemove(name string) error DockerContainerRemove(name string, update bool) error
DockerContainerStop(id string) error DockerContainerStop(id string) error
DockerContainerUpdateName(name, id string) (err error) DockerContainerUpdateName(name, id string) (err error)
DockerContainerUpdate(m model.CustomizationPostData, id string) (err error) DockerContainerUpdate(m model.CustomizationPostData, id string) (err error)
@@ -107,7 +107,7 @@ func (ds *dockerService) GetNetWorkNameByNetWorkID(id string) (string, error) {
defer cli.Close() defer cli.Close()
filter := filters.NewArgs() filter := filters.NewArgs()
filter.Add("id", id) filter.Add("id", id)
d, err := cli.NetworkList(context.Background(), types.NetworkListOptions{filter}) d, err := cli.NetworkList(context.Background(), types.NetworkListOptions{Filters: filter})
if err == nil && len(d) > 0 { if err == nil && len(d) > 0 {
return d[0].Name, nil return d[0].Name, nil
} }
@@ -158,7 +158,7 @@ func DockerEx() {
importResponse.Close() importResponse.Close()
println(string(response)) println(string(response))
if string(response) != "response" { if string(response) != "response" {
fmt.Println("expected response to contain 'response', got %s", string(response)) fmt.Printf("expected response to contain 'response', got %s", string(response))
} }
} }
@@ -187,7 +187,6 @@ func (ds *dockerService) DockerImageInfo(image string) {
if err != nil { if err != nil {
fmt.Print(err) fmt.Print(err)
} }
} }
func MsqlExec(container string) error { func MsqlExec(container string) error {
@@ -266,6 +265,8 @@ func DockerLogs() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
defer i.Close()
hdr := make([]byte, 8) hdr := make([]byte, 8)
for { for {
_, err := i.Read(hdr) _, err := i.Read(hdr)
@@ -284,7 +285,6 @@ func DockerLogs() {
_, err = i.Read(dat) _, err = i.Read(dat)
fmt.Fprint(w, string(dat)) fmt.Fprint(w, string(dat))
} }
defer i.Close()
} }
//正式内容 //正式内容
@@ -352,7 +352,7 @@ func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) e
//param udp 容器其他udp端口 //param udp 容器其他udp端口
func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId string, m model.CustomizationPostData, net string) (containerId string, err error) { func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId string, m model.CustomizationPostData, net string) (containerId string, err error) {
if len(net) == 0 { if len(net) == 0 {
net = "oasis" net = "bridge"
} }
cli, err := client2.NewClientWithOpts(client2.FromEnv) cli, err := client2.NewClientWithOpts(client2.FromEnv)
@@ -479,15 +479,13 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
if len(m.Restart) > 0 { if len(m.Restart) > 0 {
rp.Name = m.Restart rp.Name = m.Restart
} }
//fmt.Print(port)
healthTest := []string{} healthTest := []string{}
if len(port) > 0 { if len(port) > 0 {
healthTest = []string{"CMD-SHELL", "curl -f http://localhost:" + port + m.Index + " || exit 1"} healthTest = []string{"CMD-SHELL", "curl -f http://localhost:" + port + m.Index + " || exit 1"}
} }
health := &container.HealthConfig{ health := &container.HealthConfig{
Test: healthTest, Test: healthTest,
//Test: []string{},
StartPeriod: 0, StartPeriod: 0,
Retries: 1000, Retries: 1000,
} }
@@ -517,7 +515,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
} }
//删除容器 //删除容器
func (ds *dockerService) DockerContainerRemove(name string) error { func (ds *dockerService) DockerContainerRemove(name string, update bool) error {
cli, err := client2.NewClientWithOpts(client2.FromEnv) cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil { if err != nil {
return err return err
@@ -526,9 +524,11 @@ func (ds *dockerService) DockerContainerRemove(name string) error {
err = cli.ContainerRemove(context.Background(), name, types.ContainerRemoveOptions{}) err = cli.ContainerRemove(context.Background(), name, types.ContainerRemoveOptions{})
//路径处理 //路径处理
path := docker.GetDir(name, "/config") if !update {
if !file.CheckNotExist(path) { path := docker.GetDir(name, "/config")
file.RMDir(path) if !file.CheckNotExist(path) {
file.RMDir(path)
}
} }
if err != nil { if err != nil {
@@ -789,7 +789,7 @@ func (ds *dockerService) DockerNetworkModelList() []types.NetworkResource {
networks, _ := cli.NetworkList(context.Background(), types.NetworkListOptions{}) networks, _ := cli.NetworkList(context.Background(), types.NetworkListOptions{})
return networks return networks
} }
func NewDcokerService(log loger2.OLog) DockerService { func NewDockerService(log loger2.OLog) DockerService {
return &dockerService{rootDir: command2.ExecResultStr(`source ./shell/helper.sh ;GetDockerRootDir`), log: log} return &dockerService{rootDir: command2.ExecResultStr(`source ./shell/helper.sh ;GetDockerRootDir`), log: log}
} }

View File

@@ -7,5 +7,3 @@ type MysqlConfig struct {
DataBasePassword string `json:"data_base_password"` DataBasePassword string `json:"data_base_password"`
DataBaseDB string `json:"data_base_db"` DataBaseDB string `json:"data_base_db"`
} }

View File

@@ -26,14 +26,10 @@ type AppListDBModel struct {
PortMap string `json:"port_map"` PortMap string `json:"port_map"`
Label string `json:"label"` Label string `json:"label"`
EnableUPNP bool `json:"enable_upnp"` EnableUPNP bool `json:"enable_upnp"`
//Envs model.EnvArrey `json:"envs" bson:"envs"` Envs string `json:"envs"`
//Ports model.PortArrey `json:"ports" bson:"ports"` Ports string `json:"ports"`
//Volumes model.PathArrey `json:"volumes" bson:"volumes"` Volumes string `json:"volumes"`
//Devices model.PathArrey `json:"devices" bson:"devices"` Devices string `json:"devices"`
Envs string `json:"envs"`
Ports string `json:"ports"`
Volumes string `json:"volumes"`
Devices string `json:"devices"`
//Envs []model.Env `json:"envs"` //Envs []model.Env `json:"envs"`
//Ports []model.PortMap `gorm:"type:json" json:"ports"` //Ports []model.PortMap `gorm:"type:json" json:"ports"`
//Volumes []model.PathMap `gorm:"type:json" json:"volumes"` //Volumes []model.PathMap `gorm:"type:json" json:"volumes"`

View File

@@ -2,11 +2,11 @@ package model
import "time" import "time"
func (p *DDNSUpdataDBModel) TableName() string { func (p *DDNSUpdateDBModel) TableName() string {
return "o_ddns" return "o_ddns"
} }
type DDNSUpdataDBModel struct { type DDNSUpdateDBModel struct {
Id uint `gorm:"column:id;primary_key" json:"id"` Id uint `gorm:"column:id;primary_key" json:"id"`
Ipv4 string `gorm:"-"` Ipv4 string `gorm:"-"`
Ipv6 string `gorm:"-"` Ipv6 string `gorm:"-"`
@@ -17,8 +17,8 @@ type DDNSUpdataDBModel struct {
Secret string `json:"secret" form:"secret"` Secret string `json:"secret" form:"secret"`
UserName string `json:"user_name" form:"user_name"` UserName string `json:"user_name" form:"user_name"`
Password string `json:"password" form:"password"` Password string `json:"password" form:"password"`
CreatedAt time.Time `gorm:"<-:create" json:"created_at"` CreatedAt time.Time `gorm:"<-:create" json:"created_at"`
UpdatedAt time.Time `gorm:"<-:create;<-:update" json:"updated_at"` UpdatedAt time.Time `gorm:"<-:create;<-:update" json:"updated_at"`
} }
const DDNSLISTTABLENAME = "o_ddns" const DDNSLISTTABLENAME = "o_ddns"
@@ -39,9 +39,9 @@ type DDNSList struct {
//定时任务使用 //定时任务使用
type DDNSCoreList struct { type DDNSCoreList struct {
Id uint `gorm:"column:id;primary_key" json:"id"` Id uint `gorm:"column:id;primary_key" json:"id"`
Domain string `json:"domain" form:"domain"` Domain string `json:"domain" form:"domain"`
Name string `json:"domain" form:"name"` Name string `json:"name" form:"name"`
Type uint `json:"type"` Type uint `json:"type"`
Key string `json:"key"` Key string `json:"key"`
Message string `json:"message"` Message string `json:"message"`

14
service/model/o_disk.go Normal file
View File

@@ -0,0 +1,14 @@
package model
//SerialAdvanced Technology Attachment (STAT)
type SerialDisk struct {
Id uint `gorm:"column:id;primary_key" json:"id"`
DiskId string `json:"disk_id"`
Path string `json:"path"`
State int `json:"state"`
MountPoint string `json:"mount_point"`
}
func (p *SerialDisk) TableName() string {
return "o_disk"
}

View File

@@ -35,12 +35,12 @@ func NewService(db *gorm.DB, log loger2.OLog) Repository {
app: NewAppService(db, log), app: NewAppService(db, log),
ddns: NewDDNSService(db, log), ddns: NewDDNSService(db, log),
user: NewUserService(), user: NewUserService(),
docker: NewDcokerService(log), docker: NewDockerService(log),
//redis: NewRedisService(rp), //redis: NewRedisService(rp),
zerotier: NewZeroTierService(), zerotier: NewZeroTierService(),
zima: NewZiMaService(), zima: NewZiMaService(),
oapi: NewOasisService(), oapi: NewOasisService(),
disk: NewDiskService(log), disk: NewDiskService(log, db),
notify: NewNotifyService(db), notify: NewNotifyService(db),
shareDirectory: NewShareDirService(db, log), shareDirectory: NewShareDirService(db, log),
task: NewTaskService(db, log), task: NewTaskService(db, log),

View File

@@ -14,6 +14,8 @@ type SystemService interface {
UpdateSystemVersion(version string) UpdateSystemVersion(version string)
GetSystemConfigDebug() []string GetSystemConfigDebug() []string
GetCasaOSLogs(lineNumber int) string GetCasaOSLogs(lineNumber int) string
UpdateAssist()
UpSystemPort(port string)
} }
type systemService struct { type systemService struct {
log loger.OLog log loger.OLog
@@ -25,6 +27,9 @@ func (s *systemService) UpdateSystemVersion(version string) {
s.log.Error(command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/tools.sh ;update " + version)) s.log.Error(command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/tools.sh ;update " + version))
//s.log.Error(command2.ExecResultStr(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version)) //s.log.Error(command2.ExecResultStr(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version))
} }
func (s *systemService) UpdateAssist() {
s.log.Error(command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/assist.sh"))
}
func (s *systemService) GetSystemConfigDebug() []string { func (s *systemService) GetSystemConfigDebug() []string {
return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetSysInfo") return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetSysInfo")
} }
@@ -39,6 +44,13 @@ func (s *systemService) UpSystemConfig(str string, widget string) {
} }
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath) config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
} }
func (s *systemService) UpSystemPort(port string) {
if len(port) > 0 && port != config.ServerInfo.HttpPort {
config.Cfg.Section("server").Key("HttpPort").SetValue(port)
config.ServerInfo.HttpPort = port
}
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
}
func (s *systemService) GetCasaOSLogs(lineNumber int) string { func (s *systemService) GetCasaOSLogs(lineNumber int) string {
file, err := os.Open(s.log.Path()) file, err := os.Open(s.log.Path())
if err != nil { if err != nil {

View File

@@ -2,6 +2,8 @@ package service
import ( import (
json2 "encoding/json" json2 "encoding/json"
"strconv"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper" httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
@@ -9,7 +11,6 @@ import (
"github.com/IceWhaleTech/CasaOS/types" "github.com/IceWhaleTech/CasaOS/types"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"gorm.io/gorm" "gorm.io/gorm"
"strconv"
) )
type TaskService interface { type TaskService interface {

View File

@@ -34,20 +34,20 @@ type ZeroTierService interface {
DeleteNetwork(token, id string) interface{} DeleteNetwork(token, id string) interface{}
GetJoinNetworks() string GetJoinNetworks() string
} }
type zerotierstruct struct { type zerotierStruct struct {
} }
var client http.Client var client http.Client
func (c *zerotierstruct) ZeroTierJoinNetwork(networkId string) { func (c *zerotierStruct) ZeroTierJoinNetwork(networkId string) {
command2.OnlyExec(`zerotier-cli join ` + networkId) command2.OnlyExec(`zerotier-cli join ` + networkId)
} }
func (c *zerotierstruct) ZeroTierLeaveNetwork(networkId string) { func (c *zerotierStruct) ZeroTierLeaveNetwork(networkId string) {
command2.OnlyExec(`zerotier-cli leave ` + networkId) command2.OnlyExec(`zerotier-cli leave ` + networkId)
} }
//登录并获取token //登录并获取token
func (c *zerotierstruct) GetToken(username, pwd string) string { func (c *zerotierStruct) GetToken(username, pwd string) string {
if len(config.ZeroTierInfo.Token) > 0 { if len(config.ZeroTierInfo.Token) > 0 {
return config.ZeroTierInfo.Token return config.ZeroTierInfo.Token
} else { } else {
@@ -55,7 +55,7 @@ func (c *zerotierstruct) GetToken(username, pwd string) string {
} }
} }
func (c *zerotierstruct) ZeroTierRegister(email, lastName, firstName, password string) string { func (c *zerotierStruct) ZeroTierRegister(email, lastName, firstName, password string) string {
url := "https://accounts.zerotier.com/auth/realms/zerotier/protocol/openid-connect/registrations?client_id=zt-central&redirect_uri=https%3A%2F%2Fmy.zerotier.com%2Fapi%2F_auth%2Foidc%2Fcallback&response_type=code&scope=openid+profile+email+offline_access&state=state" url := "https://accounts.zerotier.com/auth/realms/zerotier/protocol/openid-connect/registrations?client_id=zt-central&redirect_uri=https%3A%2F%2Fmy.zerotier.com%2Fapi%2F_auth%2Foidc%2Fcallback&response_type=code&scope=openid+profile+email+offline_access&state=state"
@@ -210,7 +210,7 @@ func ZeroTierGet(url string, cookies []*http.Cookie, t uint8) (action string, c
} }
//模拟提交表单 //模拟提交表单
func ZeroTierPost(str bytes.Buffer, action string, cookes []*http.Cookie, isLogin bool) (url, errInfo string, err error) { func ZeroTierPost(str bytes.Buffer, action string, cookies []*http.Cookie, isLogin bool) (url, errInfo string, err error) {
req, err := http.NewRequest(http.MethodPost, action, strings.NewReader(str.String())) req, err := http.NewRequest(http.MethodPost, action, strings.NewReader(str.String()))
if err != nil { if err != nil {
return "", "", errors.New("newrequest error") return "", "", errors.New("newrequest error")
@@ -219,7 +219,7 @@ func ZeroTierPost(str bytes.Buffer, action string, cookes []*http.Cookie, isLogi
req.Header.Set(k, v) req.Header.Set(k, v)
} }
req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
for _, cookie := range cookes { for _, cookie := range cookies {
req.AddCookie(cookie) req.AddCookie(cookie)
} }
res, err := client.Do(req) res, err := client.Do(req)
@@ -273,62 +273,62 @@ func ZeroTierPost(str bytes.Buffer, action string, cookes []*http.Cookie, isLogi
} }
//获取zerotile网络列表和本地用户已加入的网络 //获取zerotile网络列表和本地用户已加入的网络
func (c *zerotierstruct) ZeroTierNetworkList(token string) (interface{}, []string) { func (c *zerotierStruct) ZeroTierNetworkList(token string) (interface{}, []string) {
url := "https://my.zerotier.com/api/network" url := "https://my.zerotier.com/api/network"
return zerotier.GetData(url, token), command2.ExecResultStrArray(`zerotier-cli listnetworks | awk 'NR>1 {print $3} {line=$0}'`) return zerotier.GetData(url, token), command2.ExecResultStrArray(`zerotier-cli listnetworks | awk 'NR>1 {print $3} {line=$0}'`)
} }
// get network info // get network info
func (c *zerotierstruct) ZeroTierGetInfo(token, id string) (interface{}, []string) { func (c *zerotierStruct) ZeroTierGetInfo(token, id string) (interface{}, []string) {
url := "https://my.zerotier.com/api/network/" + id url := "https://my.zerotier.com/api/network/" + id
info := zerotier.GetData(url, token) info := zerotier.GetData(url, token)
return info, command2.ExecResultStrArray(`zerotier-cli listnetworks | awk 'NR>1 {print $3} {line=$0}'`) return info, command2.ExecResultStrArray(`zerotier-cli listnetworks | awk 'NR>1 {print $3} {line=$0}'`)
} }
//get status //get status
func (c *zerotierstruct) ZeroTierGetStatus(token string) interface{} { func (c *zerotierStruct) ZeroTierGetStatus(token string) interface{} {
url := "https://my.zerotier.com/api/v1/status" url := "https://my.zerotier.com/api/v1/status"
info := zerotier.GetData(url, token) info := zerotier.GetData(url, token)
return info return info
} }
func (c *zerotierstruct) EditNetwork(token string, data string, id string) interface{} { func (c *zerotierStruct) EditNetwork(token string, data string, id string) interface{} {
url := "https://my.zerotier.com/api/v1/network/" + id url := "https://my.zerotier.com/api/v1/network/" + id
info := zerotier.PostData(url, token, data) info := zerotier.PostData(url, token, data)
return info return info
} }
func (c *zerotierstruct) EditNetworkMember(token string, data string, id, mId string) interface{} { func (c *zerotierStruct) EditNetworkMember(token string, data string, id, mId string) interface{} {
url := "https://my.zerotier.com/api/v1/network/" + id + "/member/" + mId url := "https://my.zerotier.com/api/v1/network/" + id + "/member/" + mId
info := zerotier.PostData(url, token, data) info := zerotier.PostData(url, token, data)
return info return info
} }
func (c *zerotierstruct) MemberList(token string, id string) interface{} { func (c *zerotierStruct) MemberList(token string, id string) interface{} {
url := "https://my.zerotier.com/api/v1/network/" + id + "/member" url := "https://my.zerotier.com/api/v1/network/" + id + "/member"
info := zerotier.GetData(url, token) info := zerotier.GetData(url, token)
return info return info
} }
func (c *zerotierstruct) DeleteMember(token string, id, mId string) interface{} { func (c *zerotierStruct) DeleteMember(token string, id, mId string) interface{} {
url := "https://my.zerotier.com/api/v1/network/" + id + "/member/" + mId url := "https://my.zerotier.com/api/v1/network/" + id + "/member/" + mId
info := zerotier.DeleteMember(url, token) info := zerotier.DeleteMember(url, token)
return info return info
} }
func (c *zerotierstruct) DeleteNetwork(token, id string) interface{} { func (c *zerotierStruct) DeleteNetwork(token, id string) interface{} {
url := "https://my.zerotier.com/api/v1/network/" + id url := "https://my.zerotier.com/api/v1/network/" + id
info := zerotier.DeleteMember(url, token) info := zerotier.DeleteMember(url, token)
return info return info
} }
func (c *zerotierstruct) CreateNetwork(token string) interface{} { func (c *zerotierStruct) CreateNetwork(token string) interface{} {
url := "https://my.zerotier.com/api/v1/network" url := "https://my.zerotier.com/api/v1/network"
info := zerotier.PostData(url, token, "{}") info := zerotier.PostData(url, token, "{}")
return info return info
} }
func (c *zerotierstruct) GetJoinNetworks() string { func (c *zerotierStruct) GetJoinNetworks() string {
json := command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetLocalJoinNetworks") json := command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetLocalJoinNetworks")
return json return json
} }
@@ -339,5 +339,5 @@ func NewZeroTierService() ZeroTierService {
return http.ErrUseLastResponse //禁止重定向 return http.ErrUseLastResponse //禁止重定向
}, },
} }
return &zerotierstruct{} return &zerotierStruct{}
} }

View File

@@ -116,7 +116,6 @@ func (c *zima) GetNetState(name string) string {
//网络信息 //网络信息
func (c *zima) GetNetInfo() []net.IOCountersStat { func (c *zima) GetNetInfo() []net.IOCountersStat {
//loger.Error("输出个内容试试")
parts, _ := net.IOCounters(true) parts, _ := net.IOCounters(true)
//fmt.Println(net.ConntrackStatsWithContext(true)) //fmt.Println(net.ConntrackStatsWithContext(true))
return parts return parts

12
shell/assist.sh Normal file
View File

@@ -0,0 +1,12 @@
#!/bin/bash
#add in v0.2.3
version_0_2_3() {
((EUID)) && sudo_cmd="sudo"
$sudo_cmd cp -rf /casaOS/server/shell/11-usb-mount.rules /etc/udev/rules.d/
$sudo_cmd chmod +x /casaOS/server/shell/usb-mount.sh
$sudo_cmd cp -rf /casaOS/server/shell/usb-mount@.service /etc/systemd/system/
}
version_0_2_3

View File

@@ -103,20 +103,22 @@ DelPartition() {
EOF EOF
} }
#添加分区 #添加分区只有一个分区
#param 路径 /dev/sdb #param 路径 /dev/sdb
#param 磁盘号 最大128 #param 要挂载的目录
#param 磁盘大小 字节 512*2048=1024kb=1M
AddPartition() { AddPartition() {
# fdisk $1 <<EOF
# n
# $2
# $3
# $4
# wq
#EOF
parted $1 mkpart primary ext4 s3 s4 DelPartition $1
parted -s $1 mklabel gpt
parted -s $1 mkpart primary ext4 0 100%
mkfs.ext4 $11
partprobe $1
# mount $11 $2
} }
#磁盘类型 #磁盘类型
@@ -151,7 +153,83 @@ GetPartitionSectors() {
fdisk $1 -l | grep "/dev/sda[1-9]" | awk 'BEGIN{OFS=","}{print $1,$2,$3,$4}' fdisk $1 -l | grep "/dev/sda[1-9]" | awk 'BEGIN{OFS=","}{print $1,$2,$3,$4}'
} }
#检查没有使用的挂载点删除文件夹
AutoRemoveUnuseDir() {
DIRECTORY="/mnt/"
dir=$(ls -l $DIRECTORY | awk '/^d/ {print $NF}')
for i in $dir; do
path="$DIRECTORY$i"
mountStr=$(mountpoint $path)
notMountpoint="is not a mountpoint"
if [[ $mountStr =~ $notMountpoint ]]; then
if [ "$(ls -A $path)" = "" ]; then
rm -fr $path
else
echo "$path is not empty"
fi
fi
done
}
#重载samba服务 #重载samba服务
ReloadSamba() { ReloadSamba() {
/etc/init.d/smbd reload /etc/init.d/smbd reload
} }
# $1=sda1
# $2=volume{1}
do_mount() {
DEVBASE=$1
DEVICE="${DEVBASE}"
# See if this drive is already mounted, and if so where
MOUNT_POINT=$(mount | grep ${DEVICE} | awk '{ print $3 }')
if [ -n "${MOUNT_POINT}" ]; then
${log} "Warning: ${DEVICE} is already mounted at ${MOUNT_POINT}"
exit 1
fi
# Get info for this drive: $ID_FS_LABEL and $ID_FS_TYPE
eval $(blkid -o udev ${DEVICE} | grep -i -e "ID_FS_LABEL" -e "ID_FS_TYPE")
LABEL=$2
if grep -q " /media/${LABEL} " /etc/mtab; then
# Already in use, make a unique one
LABEL+="-${DEVBASE}"
fi
DEV_LABEL="${LABEL}"
# Use the device name in case the drive doesn't have label
if [ -z ${DEV_LABEL} ]; then
DEV_LABEL="${DEVBASE}"
fi
MOUNT_POINT="/media/${DEV_LABEL}"
${log} "Mount point: ${MOUNT_POINT}"
mkdir -p ${MOUNT_POINT}
case ${ID_FS_TYPE} in
vfat)
mount -t vfat -o rw,relatime,users,gid=100,umask=000,shortname=mixed,utf8=1,flush ${DEVICE} ${MOUNT_POINT}
;;
ext[2-4])
mount -o noatime ${DEVICE} ${MOUNT_POINT} >/dev/null 2>&1
;;
exfat)
mount -t exfat ${DEVICE} ${MOUNT_POINT} >/dev/null 2>&1
;;
ntfs)
ntfs-3g ${DEVICE} ${MOUNT_POINT}
;;
iso9660)
mount -t iso9660 ${DEVICE} ${MOUNT_POINT}
;;
*)
/bin/rmdir "${MOUNT_POINT}"
exit 0
;;
esac
}

View File

@@ -60,7 +60,7 @@ show() {
} }
run_external_script() { run_external_script() {
show 0 "run_external_script" assist.sh
} }
update() { update() {
@@ -99,13 +99,13 @@ update() {
target_arch="386" target_arch="386"
;; ;;
*armv5*) *armv5*)
target_arch="armv5" target_arch="arm-5"
;; ;;
*armv6*) *armv6*)
target_arch="armv6" target_arch="arm-6"
;; ;;
*armv7*) *armv7*)
target_arch="armv7" target_arch="arm-7"
;; ;;
*) *)
show 1 "Aborted, unsupported or unknown architecture: $unamem" show 1 "Aborted, unsupported or unknown architecture: $unamem"

View File

@@ -1,12 +1,10 @@
#!/bin/sh #!/bin/sh
# copy to /oasis/util/shell path # copy to /casaOS/util/shell path
# chmod 755 # chmod 755
log="logger -t usb-mount.sh -s " log="logger -t usb-mount.sh -s "
${log} "变量:$1 $2"
ACTION=$1 ACTION=$1
DEVBASE=$2 DEVBASE=$2
@@ -18,10 +16,10 @@ MOUNT_POINT=$(mount | grep ${DEVICE} | awk '{ print $3 }')
do_mount() { do_mount() {
if [[ -n ${MOUNT_POINT} ]]; then if [ -n "${MOUNT_POINT}" ]; then
${log} "Warning: ${DEVICE} is already mounted at ${MOUNT_POINT}" ${log} "Warning: ${DEVICE} is already mounted at ${MOUNT_POINT}"
exit 1 exit 1
fib fi
# Get info for this drive: $ID_FS_LABEL and $ID_FS_TYPE # Get info for this drive: $ID_FS_LABEL and $ID_FS_TYPE
eval $(blkid -o udev ${DEVICE} | grep -i -e "ID_FS_LABEL" -e "ID_FS_TYPE") eval $(blkid -o udev ${DEVICE} | grep -i -e "ID_FS_LABEL" -e "ID_FS_TYPE")
@@ -33,7 +31,7 @@ do_mount() {
# Figure out a mount point to use # Figure out a mount point to use
# LABEL=${ID_FS_LABEL} # LABEL=${ID_FS_LABEL}
LABEL=${DEVBASE} LABEL=${DEVBASE}
if grep -q " /media/${LABEL} " /etc/mtab; then if grep -q " /mnt/casa_${LABEL} " /etc/mtab; then
# Already in use, make a unique one # Already in use, make a unique one
LABEL+="-${DEVBASE}" LABEL+="-${DEVBASE}"
fi fi
@@ -44,7 +42,7 @@ do_mount() {
DEV_LABEL="${DEVBASE}" DEV_LABEL="${DEVBASE}"
fi fi
MOUNT_POINT="/media/${DEV_LABEL}" MOUNT_POINT="/mnt/casa_${DEV_LABEL}"
${log} "Mount point: ${MOUNT_POINT}" ${log} "Mount point: ${MOUNT_POINT}"

View File

@@ -4,5 +4,5 @@ Description=Mount USB Drive on %i
[Service] [Service]
Type=oneshot Type=oneshot
RemainAfterExit=true RemainAfterExit=true
ExecStart=/oasis/util/shell/usb-mount.sh add %i ExecStart=/casaOS/server/shell/usb-mount.sh add %i
ExecStop=/oasis/util/shell/usb-mount.sh remove %i ExecStop=/casaOS/server/shell/usb-mount.sh remove %i

View File

@@ -1,4 +1,4 @@
package types package types
const CURRENTVERSION = "0.2.1" const CURRENTVERSION = "0.2.3"
const BODY = "<li>fixed path error</li>" const BODY = "<li>Add detailed CPU and memory statistics.</li><li>Add the multi-language function and add Chinese translation.</li><li>Add the function to modify the search engine.</li><li>Add the function of modifying the WebUI port</li><li>fixed some bugs</li><li>Preprocessing usb automounting</li><li>Update update script</li>"

View File

@@ -0,0 +1,11 @@
<svg width="72" height="72" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect opacity="0.32" x="0.435625" y="0.435625" width="71.1288" height="71.1288" rx="7.56437" fill="white" stroke="url(#paint0_linear_812_2050)" stroke-width="0.87125"/>
<path d="M36.0606 22L36.0239 50" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M22 36H50" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<defs>
<linearGradient id="paint0_linear_812_2050" x1="77.6757" y1="64.5405" x2="35.9839" y2="53.5747" gradientUnits="userSpaceOnUse">
<stop stop-color="#CBEFFF" stop-opacity="0.16"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 752 B

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long