* add send notify function

* add shell script

* add system notiry

* remove disk and test common package

* update http status

* add share function to common

* remove temp path

* remove /DATA directory initialization - moved to local-storage (#578)

* update goreleaser configuration

* wip

* change service type to notify for systemd so its status is OK only when service is initialized successfully

* update CasaOS-Common to fix runtime error

* wip

* add send notify function

* add shell script

* add system notiry

* remove disk and test common package

* update http status

* add share function to common

* remove temp path

* remove /DATA directory initialization - moved to local-storage (#578)

* update goreleaser configuration

* wip

* change service type to notify for systemd so its status is OK only when service is initialized successfully

* update CasaOS-Common to fix runtime error

* wip

* wip

* wip

* wip

* wip

* Utilization interface to supplement disk information

* fix upload file

* wip

* wip

* add update url

* wip

* wip

* add change log

* update changelog

Co-authored-by: LinkLeong <a624669980@163.com>
This commit is contained in:
Tiger Wang 2022-10-20 02:25:26 -04:00 committed by GitHub
parent 8cec47e4db
commit 381fb85b1d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
57 changed files with 1341 additions and 2370 deletions

3
.gitignore vendored
View file

@ -35,4 +35,5 @@ __debug_bin
main
github.com
.all-contributorsrc
dist
dist
CasaOS

167
.goreleaser.debug.yaml Normal file
View file

@ -0,0 +1,167 @@
# This is an example .goreleaser.yml file with some sensible defaults.
# Make sure to check the documentation at https://goreleaser.com
project_name: casaos
before:
hooks:
# You may remove this if you don't use go modules.
- go mod tidy
builds:
- id: casaos-amd64
binary: build/sysroot/usr/bin/casaos
env:
- CGO_ENABLED=1
- CC=x86_64-linux-gnu-gcc
gcflags:
- all=-N -l
ldflags:
- -extldflags "-static"
tags:
- musl
- netgo
goos:
- linux
goarch:
- amd64
hooks:
post:
- find build/sysroot -type f | xargs -L 1 realpath --relative-to=build/sysroot > build/sysroot.manifest
- id: casaos-arm64
binary: build/sysroot/usr/bin/casaos
env:
- CGO_ENABLED=1
- CC=aarch64-linux-gnu-gcc
gcflags:
- all=-N -l
ldflags:
- -extldflags "-static"
tags:
- musl
- netgo
goos:
- linux
goarch:
- arm64
hooks:
post:
- find build/sysroot -type f | xargs -L 1 realpath --relative-to=build/sysroot > build/sysroot.manifest
- id: casaos-arm-7
binary: build/sysroot/usr/bin/casaos
env:
- CGO_ENABLED=1
- CC=arm-linux-gnueabihf-gcc
gcflags:
- all=-N -l
ldflags:
- -extldflags "-static"
tags:
- musl
- netgo
goos:
- linux
goarch:
- arm
goarm:
- "7"
hooks:
post:
- find build/sysroot -type f | xargs -L 1 realpath --relative-to=build/sysroot > build/sysroot.manifest
- id: casaos-migration-tool-amd64
binary: build/sysroot/usr/bin/casaos-migration-tool
main: ./cmd/migration-tool
env:
- CGO_ENABLED=1
- CC=x86_64-linux-gnu-gcc
gcflags:
- all=-N -l
ldflags:
- -extldflags "-static"
tags:
- musl
- netgo
goos:
- linux
goarch:
- amd64
- id: casaos-migration-tool-arm64
binary: build/sysroot/usr/bin/casaos-migration-tool
main: ./cmd/migration-tool
env:
- CGO_ENABLED=1
- CC=aarch64-linux-gnu-gcc
gcflags:
- all=-N -l
ldflags:
- -extldflags "-static"
tags:
- musl
- netgo
goos:
- linux
goarch:
- arm64
- id: casaos-migration-tool-arm-7
binary: build/sysroot/usr/bin/casaos-migration-tool
main: ./cmd/migration-tool
env:
- CGO_ENABLED=1
- CC=arm-linux-gnueabihf-gcc
gcflags:
- all=-N -l
ldflags:
- -extldflags "-static"
tags:
- musl
- netgo
goos:
- linux
goarch:
- arm
goarm:
- "7"
archives:
- name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-v{{ .Version }}"
id: casaos
builds:
- casaos-amd64
- casaos-arm64
- casaos-arm-7
replacements:
arm: arm-7
files:
- build/**/*
- name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-migration-tool-v{{ .Version }}"
id: casaos-migration-tool
builds:
- casaos-migration-tool-amd64
- casaos-migration-tool-arm64
- casaos-migration-tool-arm-7
replacements:
arm: arm-7
files:
- build/sysroot/etc/**/*
checksum:
name_template: "checksums.txt"
snapshot:
name_template: "{{ incpatch .Version }}"
changelog:
sort: asc
filters:
exclude:
- "^docs:"
- "^test:"
# release:
# github:
# owner: IceWhaleTech
# name: CasaOS
# draft: true
# prerelease: auto
# mode: replace
# name_template: "v{{ .Version }}"
release:
github:
owner: IceWhaleTech
name: CasaOS
draft: true
prerelease: auto
mode: replace
name_template: "v{{ .Version }}"

View file

@ -117,7 +117,7 @@ builds:
goarch:
- arm
goarm:
- "7"
- "7"
archives:
- name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-v{{ .Version }}"
id: casaos
@ -159,9 +159,9 @@ changelog:
# name_template: "v{{ .Version }}"
release:
github:
owner: LinkLeong
name: casaos-alpha
owner: IceWhaleTech
name: CasaOS
draft: true
prerelease: auto
mode: replace
name_template: "v{{ .Version }}"
name_template: "v{{ .Version }}"

View file

@ -18,6 +18,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
## [0.3.7]
### Added
- [Storage] Disk merge (Beta), you can merge multiple disks into a single storage space (currently you need to enable this feature from the command line)
### Changed
- [Files] Changed the cache file storage location, now the file upload size is not limited by the system disk capacity.
- [Scripts] Updated installation and upgrade scripts to support more Debian-based Linux distributions.
- [Engineering] Refactored Local Storage into a standalone service as part of CasaOS modularization.
### Fixed
- [Apps] App list update mechanism improved, now you can see the latest apps in App Store immediately.
- [Storage] Fixed a lot of known issues
## [0.3.6-alpha.1] - 2022-09-06

View file

@ -60,8 +60,6 @@ BUILD_PATH=$(dirname "${BASH_SOURCE[0]}")/../../..
SOURCE_ROOT=${BUILD_PATH}/sysroot
APP_NAME="casaos"
# APP_NAME_FORMAL="CasaOS"
APP_NAME_FORMAL="casaos-alpha"
# check if migration is needed
SOURCE_BIN_PATH=${SOURCE_ROOT}/usr/bin
@ -85,45 +83,6 @@ if [ "${NEED_MIGRATION}" = "false" ]; then
exit 0
fi
MIGRATION_SERVICE_DIR=${1}
if [ -z "${MIGRATION_SERVICE_DIR}" ]; then
MIGRATION_SERVICE_DIR=${BUILD_PATH}/scripts/migration/service.d/${APP_NAME}
fi
MIGRATION_LIST_FILE=${MIGRATION_SERVICE_DIR}/migration.list
MIGRATION_PATH=()
CURRENT_VERSION_FOUND="false"
# a VERSION_PAIR looks like "v0.3.5 v0.3.6-alpha2"
#
# - "v0.3.5" is the current version installed on this host
# - "v0.3.6-alpha2" is the version of the migration tool from GitHub
while read -r VERSION_PAIR; do
if [ -z "${VERSION_PAIR}" ]; then
continue
fi
# obtain "v0.3.5" from "v0.3.5 v0.3.6-alpha2"
VER1=$(echo "${VERSION_PAIR}" | cut -d' ' -f1)
# obtain "v0.3.6-alpha2" from "v0.3.5 v0.3.6-alpha2"
VER2=$(echo "${VERSION_PAIR}" | cut -d' ' -f2)
if [ "${CURRENT_VERSION}" = "${VER1// /}" ] || [ "${CURRENT_VERSION}" = "LEGACY_WITHOUT_VERSION" ]; then
CURRENT_VERSION_FOUND="true"
fi
if [ "${CURRENT_VERSION_FOUND}" = "true" ]; then
MIGRATION_PATH+=("${VER2// /}")
fi
done < "${MIGRATION_LIST_FILE}"
if [ ${#MIGRATION_PATH[@]} -eq 0 ]; then
__warning "No migration path found from ${CURRENT_VERSION} to ${SOURCE_VERSION}"
exit 0
fi
ARCH="unknown"
case $(uname -m) in
@ -141,21 +100,59 @@ case $(uname -m) in
;;
esac
__info "ARCH: ${ARCH}"
MIGRATION_SERVICE_DIR=${1}
if [ -z "${MIGRATION_SERVICE_DIR}" ]; then
MIGRATION_SERVICE_DIR=${BUILD_PATH}/scripts/migration/service.d/${APP_NAME}
fi
MIGRATION_LIST_FILE=${MIGRATION_SERVICE_DIR}/migration.list
MIGRATION_PATH=()
CURRENT_VERSION_FOUND="false"
# a VERSION_PAIR looks like "v0.3.5 <url>"
#
# - "v0.3.5" is the current version installed on this host
# - "<url>" is the url of the migration tool
while read -r VERSION_PAIR; do
if [ -z "${VERSION_PAIR}" ]; then
continue
fi
# obtain "v0.3.5" from "v0.3.5 v0.3.6-alpha2"
VER1=$(echo "${VERSION_PAIR}" | cut -d' ' -f1)
# obtain "<url>" from "v0.3.5 <url>"
URL=$(eval echo "${VERSION_PAIR}" | cut -d' ' -f2)
if [ "${CURRENT_VERSION}" = "${VER1// /}" ] || [ "${CURRENT_VERSION}" = "LEGACY_WITHOUT_VERSION" ]; then
CURRENT_VERSION_FOUND="true"
fi
if [ "${CURRENT_VERSION_FOUND}" = "true" ]; then
MIGRATION_PATH+=("${URL// /}")
fi
done < "${MIGRATION_LIST_FILE}"
if [ ${#MIGRATION_PATH[@]} -eq 0 ]; then
__warning "No migration path found from ${CURRENT_VERSION} to ${SOURCE_VERSION}"
exit 0
fi
pushd "${MIGRATION_SERVICE_DIR}"
{ for VER2 in "${MIGRATION_PATH[@]}"; do
MIGRATION_TOOL_FILE=linux-"${ARCH}"-"${APP_NAME}"-migration-tool-"${VER2}".tar.gz
{ for URL in "${MIGRATION_PATH[@]}"; do
MIGRATION_TOOL_FILE=$(basename "${URL}")
if [ -f "${MIGRATION_TOOL_FILE}" ]; then
__info "Migration tool ${MIGRATION_TOOL_FILE} exists. Skip downloading."
continue
fi
MIGRATION_TOOL_URL=https://github.com/LinkLeong/"${APP_NAME_FORMAL}"/releases/download/"${VER2}"/linux-"${ARCH}"-"${APP_NAME}"-migration-tool-"${VER2}".tar.gz
echo "Dowloading ${MIGRATION_TOOL_URL}..."
curl -sL -O "${MIGRATION_TOOL_URL}"
__info "Dowloading ${URL}..."
curl -fsSL -o "${MIGRATION_TOOL_FILE}" -O "${URL}"
done
} || {
popd
@ -163,8 +160,8 @@ pushd "${MIGRATION_SERVICE_DIR}"
}
{
for VER2 in "${MIGRATION_PATH[@]}"; do
MIGRATION_TOOL_FILE=linux-"${ARCH}"-"${APP_NAME}"-migration-tool-"${VER2}".tar.gz
for URL in "${MIGRATION_PATH[@]}"; do
MIGRATION_TOOL_FILE=$(basename "${URL}")
__info "Extracting ${MIGRATION_TOOL_FILE}..."
tar zxvf "${MIGRATION_TOOL_FILE}" || __error "Failed to extract ${MIGRATION_TOOL_FILE}"

View file

@ -1,3 +1,3 @@
LEGACY_WITHOUT_VERSION v0.3.6
v0.3.5 v0.3.6
v0.3.5.1 v0.3.6
LEGACY_WITHOUT_VERSION https://github.com/IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz
v0.3.5 https://github.com/IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz
v0.3.5.1 https://github.com/IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz

View file

@ -31,15 +31,10 @@ if [ ! -f "${CONF_FILE}" ]; then
cp -v "${CONF_FILE_SAMPLE}" "${CONF_FILE}"
fi
if systemctl is-active "${APP_NAME}.service" &>/dev/null ;then
echo "server started"
else
# enable and start service
systemctl daemon-reload
rm -rf /etc/systemd/system/casaos.service # remove old service file
echo "Enabling service..."
systemctl enable --force --no-ask-password "${APP_NAME}.service"
systemctl daemon-reload
echo "Starting service..."
systemctl start --force --no-ask-password "${APP_NAME}.service"
fi
# enable service (without starting)
echo "Enabling service..."
systemctl enable --force --no-ask-password "${APP_NAME}.service"

View file

@ -11,7 +11,6 @@ DateFormat = 2006-01-02
DBPath = /var/lib/casaos
ShellPath = /usr/share/casaos/shell
UserDataPath = /var/lib/casaos/conf
TempPath = /var/lib/casaos/temp
[server]
RunMode = release

View file

@ -1,12 +1,13 @@
[Unit]
After=casaos-gateway.service
ConditionFileNotEmpty=/etc/casaos/casaos.conf
Description=CasaOS Service
Description=CasaOS Main Service
[Service]
ExecStart=/usr/bin/casaos -c /etc/casaos/casaos.conf
PIDFile=/var/run/casaos/casaos.pid
Restart=always
Type=notify
[Install]
WantedBy=multi-user.target

View file

@ -0,0 +1,46 @@
#!/bin/bash
set -e
readonly APP_NAME_SHORT=casaos
__get_setup_script_directory_by_os_release() {
pushd "$(dirname "${BASH_SOURCE[0]}")/../service.d/${APP_NAME_SHORT}" &>/dev/null
{
# shellcheck source=/dev/null
{
source /etc/os-release
{
pushd "${ID}"/"${VERSION_CODENAME}" &>/dev/null
} || {
pushd "${ID}" &>/dev/null
} || {
pushd "${ID_LIKE}" &>/dev/null
} || {
echo "Unsupported OS: ${ID} ${VERSION_CODENAME} (${ID_LIKE})"
exit 1
}
pwd
popd &>/dev/null
} || {
echo "Unsupported OS: unknown"
exit 1
}
}
popd &>/dev/null
}
SETUP_SCRIPT_DIRECTORY=$(__get_setup_script_directory_by_os_release)
readonly SETUP_SCRIPT_DIRECTORY
readonly SETUP_SCRIPT_FILENAME="cleanup-${APP_NAME_SHORT}.sh"
readonly SETUP_SCRIPT_FILEPATH="${SETUP_SCRIPT_DIRECTORY}/${SETUP_SCRIPT_FILENAME}"
echo "🟩 Running ${SETUP_SCRIPT_FILENAME}..."
$SHELL "${SETUP_SCRIPT_FILEPATH}" "${BUILD_PATH}"

View file

@ -0,0 +1 @@
../cleanup-casaos.sh

View file

@ -0,0 +1,204 @@
#!/bin/bash
set -e
readonly CASA_SERVICES=(
"casaos.service"
"devmon@devmon.service"
)
readonly CASA_EXEC=casaos
readonly CASA_CONF=/etc/casaos/casaos.conf
readonly CASA_URL=/var/run/casaos/casaos.url
readonly CASA_SERVICE_USR=/usr/lib/systemd/system/casaos.service
readonly CASA_SERVICE_LIB=/lib/systemd/system/casaos.service
readonly CASA_SERVICE_ETC=/etc/systemd/system/casaos.service
# Old Casa Files
readonly CASA_PATH=/casaOS
readonly CASA_CONF_PATH_OLD=/etc/casaos.conf
readonly aCOLOUR=(
'\e[38;5;154m' # green | Lines, bullets and separators
'\e[1m' # Bold white | Main descriptions
'\e[90m' # Grey | Credits
'\e[91m' # Red | Update notifications Alert
'\e[33m' # Yellow | Emphasis
)
Show() {
# OK
if (($1 == 0)); then
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} OK $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
# FAILED
elif (($1 == 1)); then
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[3]}FAILED$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
# INFO
elif (($1 == 2)); then
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} INFO $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
# NOTICE
elif (($1 == 3)); then
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[4]}NOTICE$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
fi
}
Warn() {
echo -e "${aCOLOUR[3]}$1$COLOUR_RESET"
}
trap 'onCtrlC' INT
onCtrlC() {
echo -e "${COLOUR_RESET}"
exit 1
}
Detecting_CasaOS() {
if [[ ! -x "$(command -v ${CASA_EXEC})" ]]; then
Show 2 "CasaOS is not detected, exit the script."
exit 1
else
Show 0 "This script will delete the containers you no longer use, and the CasaOS configuration files."
fi
}
Uninstall_Container() {
if [[ ${UNINSTALL_ALL_CONTAINER} == true && "$(docker ps -aq)" != "" ]]; then
Show 2 "Start deleting containers."
docker stop "$(docker ps -aq)" || Show 1 "Failed to stop all containers."
docker rm "$(docker ps -aq)" || Show 1 "Failed to delete all containers."
fi
}
Remove_Images() {
if [[ ${REMOVE_IMAGES} == "all" && "$(docker images -q)" != "" ]]; then
Show 2 "Start deleting all images."
docker rmi "$(docker images -q)" || Show 1 "Failed to delete all images."
elif [[ ${REMOVE_IMAGES} == "unuse" && "$(docker images -q)" != "" ]]; then
Show 2 "Start deleting unuse images."
docker image prune -af || Show 1 "Failed to delete unuse images."
fi
}
Uninstall_Casaos() {
for SERVICE in "${CASA_SERVICES[@]}"; do
Show 2 "Stopping ${SERVICE}..."
systemctl disable --now "${SERVICE}" || Show 3 "Failed to disable ${SERVICE}"
done
# Remove Service file
if [[ -f ${CASA_SERVICE_USR} ]]; then
rm -rvf ${CASA_SERVICE_USR}
fi
if [[ -f ${CASA_SERVICE_LIB} ]]; then
rm -rvf ${CASA_SERVICE_LIB}
fi
if [[ -f ${CASA_SERVICE_ETC} ]]; then
rm -rvf ${CASA_SERVICE_ETC}
fi
# Old Casa Files
if [[ -d ${CASA_PATH} ]]; then
rm -rvf ${CASA_PATH} || Show 1 "Failed to delete legacy CasaOS files."
fi
if [[ -f ${CASA_CONF_PATH_OLD} ]]; then
rm -rvf ${CASA_CONF_PATH_OLD}
fi
# New Casa Files
if [[ ${REMOVE_APP_DATA} = true ]]; then
rm -rvf /DATA/AppData || Show 1 "Failed to delete AppData."
fi
rm -rvf "$(which ${CASA_EXEC})" || Show 3 "Failed to remove ${CASA_EXEC}"
rm -rvf ${CASA_CONF} || Show 3 "Failed to remove ${CASA_CONF}"
rm -rvf ${CASA_URL} || Show 3 "Failed to remove ${CASA_URL}"
rm -rvf /var/lib/casaos/app_category.json
rm -rvf /var/lib/casaos/app_list.json
rm -rvf /var/lib/casaos/docker_root
}
Detecting_CasaOS
while true; do
echo -n -e " ${aCOLOUR[4]}Do you want delete all containers? Y/n :${COLOUR_RESET}"
read -r input
case $input in
[yY][eE][sS] | [yY])
UNINSTALL_ALL_CONTAINER=true
break
;;
[nN][oO] | [nN])
UNINSTALL_ALL_CONTAINER=false
break
;;
*)
Warn " Invalid input..."
;;
esac
done
if [[ ${UNINSTALL_ALL_CONTAINER} == true ]]; then
while true; do
echo -n -e " ${aCOLOUR[4]}Do you want delete all images? Y/n :${COLOUR_RESET}"
read -r input
case $input in
[yY][eE][sS] | [yY])
REMOVE_IMAGES="all"
break
;;
[nN][oO] | [nN])
REMOVE_IMAGES="none"
break
;;
*)
Warn " Invalid input..."
;;
esac
done
while true; do
echo -n -e " ${aCOLOUR[4]}Do you want delete all AppData of CasaOS? Y/n :${COLOUR_RESET}"
read -r input
case $input in
[yY][eE][sS] | [yY])
REMOVE_APP_DATA=true
break
;;
[nN][oO] | [nN])
REMOVE_APP_DATA=false
break
;;
*)
Warn " Invalid input..."
;;
esac
done
else
while true; do
echo -n -e " ${aCOLOUR[4]}Do you want to delete all images that are not used by the container? Y/n :${COLOUR_RESET}"
read -r input
case $input in
[yY][eE][sS] | [yY])
REMOVE_IMAGES="unuse"
break
;;
[nN][oO] | [nN])
REMOVE_IMAGES="none"
break
;;
*)
Warn " Invalid input..."
;;
esac
done
fi
Uninstall_Container
Remove_Images
Uninstall_Casaos

View file

@ -0,0 +1 @@
../debian/cleanup-casaos.sh

View file

@ -0,0 +1 @@
../../debian/bullseye/cleanup-casaos.sh

View file

@ -9,4 +9,4 @@
###
curl -fsSL https://raw.githubusercontent.com/IceWhaleTech/get/main/update.sh | bash
curl -fsSL https://raw.githubusercontent.com/IceWhaleTech/get/main/update.sh | bash

View file

@ -1,13 +1,3 @@
/*
* @Author: LinkLeong link@icewhale.org
* @Date: 2022-08-30 22:15:30
* @LastEditors: LinkLeong
* @LastEditTime: 2022-08-30 22:15:47
* @FilePath: /CasaOS/cmd/migration-tool/log.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package main
import (

View file

@ -28,25 +28,29 @@ const (
casaosServiceName = "casaos.service"
)
var _logger *Logger
var sqliteDB *gorm.DB
var (
_logger *Logger
sqliteDB *gorm.DB
)
var configFlag = ""
var dbFlag = ""
var (
configFlag = ""
dbFlag = ""
)
func init() {
config.InitSetup(configFlag)
config.UpdateSetup()
if len(dbFlag) == 0 {
dbFlag = config.AppInfo.DBPath + "/db"
}
sqliteDB = sqlite.GetDb(dbFlag)
//gredis.GetRedisConn(config.RedisInfo),
// gredis.GetRedisConn(config.RedisInfo),
service.MyService = service.NewService(sqliteDB, "")
}
func main() {
versionFlag := flag.Bool("v", false, "version")
debugFlag := flag.Bool("d", true, "debug")
@ -79,7 +83,7 @@ func main() {
}
migrationTools := []interfaces.MigrationTool{
NewMigrationToolFor_035(),
// nothing to migrate from last version
}
var selectedMigrationTool interfaces.MigrationTool
@ -110,8 +114,7 @@ func main() {
panic(err)
}
selectedMigrationTool.PostMigrate()
_logger.Info("casaos migration ok")
//panic(err)
if err := selectedMigrationTool.PostMigrate(); err != nil {
_logger.Error("Migration succeeded, but post-migration failed: %s", err)
}
}

View file

@ -1,182 +0,0 @@
/*
* @Author: LinkLeong link@icewhale.org
* @Date: 2022-08-24 17:36:00
* @LastEditors: LinkLeong
* @LastEditTime: 2022-09-05 11:24:27
* @FilePath: /CasaOS/cmd/migration-tool/migration-034-035.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package main
import (
"io"
"io/ioutil"
"os"
"path"
"strings"
interfaces "github.com/IceWhaleTech/CasaOS-Common"
"github.com/IceWhaleTech/CasaOS-Common/utils/version"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/service"
)
type migrationTool struct{}
func (u *migrationTool) IsMigrationNeeded() (bool, error) {
majorVersion, minorVersion, patchVersion, err := version.DetectLegacyVersion()
if err != nil {
if err == version.ErrLegacyVersionNotFound {
return false, nil
}
return false, err
}
if majorVersion > 0 {
return false, nil
}
if minorVersion > 3 {
return false, nil
}
if minorVersion == 3 && patchVersion > 5 {
return false, nil
}
_logger.Info("Migration is needed for a CasaOS version 0.3.5 and older...")
return true, nil
}
func (u *migrationTool) PreMigrate() error {
return nil
}
func (u *migrationTool) Migrate() error {
if service.MyService.System().GetSysInfo().KernelArch == "aarch64" && config.ServerInfo.USBAutoMount != "True" && strings.Contains(service.MyService.System().GetDeviceTree(), "Raspberry Pi") {
service.MyService.System().UpdateUSBAutoMount("False")
service.MyService.System().ExecUSBAutoMountShell("False")
}
newAPIUrl := "https://api.casaos.io/casaos-api"
if config.ServerInfo.ServerApi == "https://api.casaos.zimaboard.com" {
config.ServerInfo.ServerApi = newAPIUrl
config.Cfg.Section("server").Key("ServerApi").SetValue(newAPIUrl)
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
}
command.OnlyExec("curl -fsSL https://raw.githubusercontent.com/IceWhaleTech/get/main/assist.sh | bash")
if !file.CheckNotExist("/casaOS") {
command.OnlyExec("source /casaOS/server/shell/update.sh ;")
command.OnlyExec("source " + config.AppInfo.ShellPath + "/delete-old-service.sh ;")
}
service.MyService.App().ImportApplications(true)
src := "/casaOS/server/conf/conf.ini"
if file.Exists(src) {
dst := "/etc/casaos/casaos.conf"
source, err := os.Open(src)
if err != nil {
return err
}
defer source.Close()
destination, err := os.Create(dst)
if err != nil {
return err
}
defer destination.Close()
_, err = io.Copy(destination, source)
if err != nil {
return err
}
}
if file.Exists("/casaOS/server/db") {
var fds []os.FileInfo
var err error
to := "/var/lib/casaos/db"
file.IsNotExistMkDir(to)
from := "/casaOS/server/db"
if fds, err = ioutil.ReadDir(from); err != nil {
return err
}
for _, fd := range fds {
srcfp := path.Join(from, fd.Name())
dstfp := path.Join(to, fd.Name())
source, err := os.Open(srcfp)
if err != nil {
return err
}
defer source.Close()
destination, err := os.Create(dstfp)
if err != nil {
return err
}
defer destination.Close()
_, err = io.Copy(destination, source)
if err != nil {
return err
}
}
}
if file.Exists("/casaOS/server/conf") {
var fds []os.FileInfo
var err error
to := "/var/lib/casaos/conf"
file.IsNotExistMkDir(to)
from := "/casaOS/server/conf"
if fds, err = ioutil.ReadDir(from); err != nil {
return err
}
for _, fd := range fds {
fExt := path.Ext(fd.Name())
if fExt != ".json" {
continue
}
srcfp := path.Join(from, fd.Name())
dstfp := path.Join(to, fd.Name())
source, err := os.Open(srcfp)
if err != nil {
return err
}
defer source.Close()
destination, err := os.Create(dstfp)
if err != nil {
return err
}
defer destination.Close()
_, err = io.Copy(destination, source)
if err != nil {
return err
}
}
}
_logger.Info("update done")
return nil
}
func (u *migrationTool) PostMigrate() error {
return nil
}
func NewMigrationToolFor_035() interfaces.MigrationTool {
return &migrationTool{}
}

View file

@ -0,0 +1,60 @@
/*
* @Author: LinkLeong link@icewhale.org
* @Date: 2022-08-24 17:36:00
* @LastEditors: LinkLeong
* @LastEditTime: 2022-09-05 11:24:27
* @FilePath: /CasaOS/cmd/migration-tool/migration-034-035.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package main
import (
interfaces "github.com/IceWhaleTech/CasaOS-Common"
"github.com/IceWhaleTech/CasaOS-Common/utils/version"
)
type migrationTool struct{}
func (u *migrationTool) IsMigrationNeeded() (bool, error) {
majorVersion, minorVersion, patchVersion, err := version.DetectLegacyVersion()
if err != nil {
if err == version.ErrLegacyVersionNotFound {
return false, nil
}
return false, err
}
if majorVersion > 0 {
return false, nil
}
if minorVersion > 3 {
return false, nil
}
if minorVersion == 3 && patchVersion > 5 {
return false, nil
}
_logger.Info("Migration is needed for a CasaOS version 0.3.5 and older...")
return true, nil
}
func (u *migrationTool) PreMigrate() error {
return nil
}
func (u *migrationTool) Migrate() error {
return nil
}
func (u *migrationTool) PostMigrate() error {
return nil
}
func NewMigrationToolFor_036() interfaces.MigrationTool {
return &migrationTool{}
}

89
common/notify.go Normal file
View file

@ -0,0 +1,89 @@
package common
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"os"
"path/filepath"
"strings"
)
const (
CasaOSURLFilename = "casaos.url"
APICasaOSNotify = "/v1/notify"
)
type NotifyService interface {
SendNotify(path string, message map[string]interface{}) error
SendSystemStatusNotify(message map[string]interface{}) error
}
type notifyService struct {
address string
}
func (n *notifyService) SendNotify(path string, message map[string]interface{}) error {
url := strings.TrimSuffix(n.address, "/") + APICasaOSNotify + "/" + path
body, err := json.Marshal(message)
if err != nil {
return err
}
response, err := http.Post(url, "application/json", bytes.NewBuffer(body))
if err != nil {
return err
}
if response.StatusCode != http.StatusOK {
return errors.New("failed to send notify (status code: " + fmt.Sprint(response.StatusCode) + ")")
}
return nil
}
// disk: "sys_disk":{"size":56866869248,"avail":5855485952,"health":true,"used":48099700736}
// usb: "sys_usb":[{"name": "sdc","size": 7747397632,"model": "DataTraveler_2.0","avail": 7714418688,"children": null}]
func (n *notifyService) SendSystemStatusNotify(message map[string]interface{}) error {
url := strings.TrimSuffix(n.address, "/") + APICasaOSNotify + "/system_status"
fmt.Println(url)
body, err := json.Marshal(message)
if err != nil {
return err
}
response, err := http.Post(url, "application/json", bytes.NewBuffer(body))
if err != nil {
return err
}
if response.StatusCode != http.StatusOK {
return errors.New("failed to send notify (status code: " + fmt.Sprint(response.StatusCode) + ")")
}
return nil
}
func NewNotifyService(runtimePath string) (NotifyService, error) {
casaosAddressFile := filepath.Join(runtimePath, CasaOSURLFilename)
buf, err := os.ReadFile(casaosAddressFile)
if err != nil {
return nil, err
}
address := string(buf)
response, err := http.Get(address + "/ping")
if err != nil {
return nil, err
}
if response.StatusCode != 200 {
return nil, errors.New("failed to ping casaos service")
}
return &notifyService{
address: address,
}, nil
}

29
common/notify_test.go Normal file
View file

@ -0,0 +1,29 @@
package common
import "testing"
func TestSendNotify(t *testing.T) {
notify, err := NewNotifyService("/var/run/casaos")
if err != nil {
t.Fatal(err)
}
err = notify.SendNotify("test", map[string]interface{}{
"test": "test",
})
if err != nil {
t.Fatal(err)
}
}
func TestSendSystemStatusNotify(t *testing.T) {
notify, err := NewNotifyService("/var/run/casaos")
if err != nil {
t.Fatal(err)
}
err = notify.SendSystemStatusNotify(map[string]interface{}{
"sys_usb": `[{"name": "sdc","size": 7747397632,"model": "DataTraveler_2.0","avail": 7714418688,"children": null}]`,
})
if err != nil {
t.Fatal(err)
}
}

78
common/share.go Normal file
View file

@ -0,0 +1,78 @@
package common
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"os"
"path/filepath"
"strings"
)
const (
APICasaOSShare = "/v1/samba/shares"
)
type ShareService interface {
DeleteShare(id string) error
}
type shareService struct {
address string
}
func (n *shareService) DeleteShare(id string) error {
url := strings.TrimSuffix(n.address, "/") + APICasaOSShare + "/" + id
fmt.Println(url)
message := "{}"
body, err := json.Marshal(message)
if err != nil {
return err
}
client := &http.Client{}
// Create request
req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(body))
if err != nil {
return err
}
// Fetch Request
response, err := client.Do(req)
if err != nil {
return err
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK {
return errors.New("failed to send share (status code: " + fmt.Sprint(response.StatusCode) + ")")
}
return nil
}
func NewShareService(runtimePath string) (ShareService, error) {
casaosAddressFile := filepath.Join(runtimePath, CasaOSURLFilename)
buf, err := os.ReadFile(casaosAddressFile)
if err != nil {
return nil, err
}
address := string(buf)
response, err := http.Get(address + "/ping")
if err != nil {
return nil, err
}
if response.StatusCode != 200 {
return nil, errors.New("failed to ping casaos service")
}
return &shareService{
address: address,
}, nil
}

14
common/share_test.go Normal file
View file

@ -0,0 +1,14 @@
package common
import "testing"
func TestDeleteShare(t *testing.T) {
share, err := NewShareService("/var/run/casaos")
if err != nil {
t.Fatal(err)
}
err = share.DeleteShare("1")
if err != nil {
t.Fatal(err)
}
}

View file

@ -11,7 +11,6 @@ DateFormat = 2006-01-02
DBPath = /var/lib/casaos
ShellPath = /usr/share/casaos/shell
UserDataPath = /var/lib/casaos/conf
TempPath = /var/lib/casaos/temp
[server]
RunMode = release

4
go.mod
View file

@ -4,13 +4,14 @@ go 1.16
require (
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d
github.com/IceWhaleTech/CasaOS-Common v0.0.0-20220909125858-92fc5b2e0ae5
github.com/IceWhaleTech/CasaOS-Common v0.0.0-20220929035515-b1287110d6d8
github.com/IceWhaleTech/CasaOS-Gateway v0.3.6
github.com/Microsoft/go-winio v0.5.0 // indirect
github.com/ambelovsky/go-structs v1.1.0 // indirect
github.com/ambelovsky/gosf v0.0.0-20201109201340-237aea4d6109
github.com/ambelovsky/gosf-socketio v0.0.0-20201109193639-add9d32f8b19 // indirect
github.com/containerd/containerd v1.5.7 // indirect
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e
github.com/disintegration/imaging v1.6.2
github.com/docker/distribution v2.8.0+incompatible // indirect
github.com/docker/docker v20.10.7+incompatible
@ -34,7 +35,6 @@ require (
github.com/morikuni/aec v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // 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/robfig/cron v1.2.0
github.com/satori/go.uuid v1.2.0

6
go.sum
View file

@ -84,8 +84,8 @@ github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d/go.mod h1:lW9x+yEjqKdPbE3+cf2fGPJXCw/hChX3Omi9QHTLFsQ=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/IceWhaleTech/CasaOS-Common v0.0.0-20220901034123-ca130f6b5ce9/go.mod h1:2MiivEMzvh41codhEKUcn46WK3Ffesop/04qa9jsvQk=
github.com/IceWhaleTech/CasaOS-Common v0.0.0-20220909125858-92fc5b2e0ae5 h1:vgAf0jVKCBo3wyjOZ4z9tB77lVrgIfz2CcQX2+4JTSI=
github.com/IceWhaleTech/CasaOS-Common v0.0.0-20220909125858-92fc5b2e0ae5/go.mod h1:2MiivEMzvh41codhEKUcn46WK3Ffesop/04qa9jsvQk=
github.com/IceWhaleTech/CasaOS-Common v0.0.0-20220929035515-b1287110d6d8 h1:r8nhgQ6tnrn6ikXN9aLH/K4H4H64Nc0hZ6jyW2B22x0=
github.com/IceWhaleTech/CasaOS-Common v0.0.0-20220929035515-b1287110d6d8/go.mod h1:2MiivEMzvh41codhEKUcn46WK3Ffesop/04qa9jsvQk=
github.com/IceWhaleTech/CasaOS-Gateway v0.3.6 h1:2tQQo85+jzbbjqIsKKn77QlAA73bc7vZsVCFvWnK4mg=
github.com/IceWhaleTech/CasaOS-Gateway v0.3.6/go.mod h1:hnZwGUzcOyiufMpVO7l3gu2gAm6Ws4TY4Nlj3kMshXA=
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
@ -814,8 +814,6 @@ github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZO
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/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
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=

69
main.go
View file

@ -5,6 +5,7 @@ import (
"fmt"
"net"
"net/http"
"path/filepath"
"time"
"github.com/IceWhaleTech/CasaOS-Gateway/common"
@ -12,10 +13,13 @@ import (
"github.com/IceWhaleTech/CasaOS/pkg/cache"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/sqlite"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/IceWhaleTech/CasaOS/route"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/IceWhaleTech/CasaOS/types"
"github.com/coreos/go-systemd/daemon"
"go.uber.org/zap"
"github.com/robfig/cron"
"gorm.io/gorm"
@ -25,9 +29,11 @@ const LOCALHOST = "127.0.0.1"
var sqliteDB *gorm.DB
var configFlag = flag.String("c", "", "config address")
var dbFlag = flag.String("db", "", "db path")
var versionFlag = flag.Bool("v", false, "version")
var (
configFlag = flag.String("c", "", "config address")
dbFlag = flag.String("db", "", "db path")
versionFlag = flag.Bool("v", false, "version")
)
func init() {
flag.Parse()
@ -36,7 +42,6 @@ func init() {
return
}
config.InitSetup(*configFlag)
config.UpdateSetup()
loger.LogInit()
if len(*dbFlag) == 0 {
@ -44,7 +49,7 @@ func init() {
}
sqliteDB = sqlite.GetDb(*dbFlag)
//gredis.GetRedisConn(config.RedisInfo),
// gredis.GetRedisConn(config.RedisInfo),
service.MyService = service.NewService(sqliteDB, config.CommonInfo.RuntimePath)
@ -57,7 +62,6 @@ func init() {
// go service.LoopFriend()
// go service.MyService.App().CheckNewImage()
}
// @title casaOS API
@ -77,22 +81,21 @@ func main() {
return
}
go route.SocketInit(service.NotifyMsg)
go route.MonitoryUSB()
//model.Setup()
//gredis.Setup()
// model.Setup()
// gredis.Setup()
r := route.InitRouter()
//service.SyncTask(sqliteDB)
// service.SyncTask(sqliteDB)
cron2 := cron.New()
//every day execution
// every day execution
err := cron2.AddFunc("0/5 * * * * *", func() {
if service.ClientCount > 0 {
//route.SendNetINfoBySocket()
//route.SendCPUBySocket()
//route.SendMemBySocket()
// route.SendNetINfoBySocket()
// route.SendCPUBySocket()
// route.SendMemBySocket()
// route.SendDiskBySocket()
//route.SendUSBBySocket()
// route.SendUSBBySocket()
route.SendAllHardwareStatusBySocket()
}
})
@ -107,7 +110,7 @@ func main() {
if err != nil {
panic(err)
}
routers := []string{"sys", "apps", "container", "app-categories", "port", "file", "folder", "batch", "image", "disks", "storage", "samba"}
routers := []string{"sys", "apps", "container", "app-categories", "port", "file", "folder", "batch", "image", "samba", "notify"}
for _, v := range routers {
err = service.MyService.Gateway().CreateRoute(&common.Route{
Path: "/v1/" + v,
@ -121,7 +124,7 @@ func main() {
}
go func() {
time.Sleep(time.Second * 2)
//v0.3.6
// v0.3.6
if config.ServerInfo.HttpPort != "" {
changePort := common.ChangePortRequest{}
changePort.Port = config.ServerInfo.HttpPort
@ -133,15 +136,29 @@ func main() {
}
}()
// s := &http.Server{
// Addr: listener.Addr().String(), //fmt.Sprintf(":%v", config.ServerInfo.HttpPort),
// Handler: r,
// ReadTimeout: 60 * time.Second,
// WriteTimeout: 60 * time.Second,
// MaxHeaderBytes: 1 << 20,
// }
// s.ListenAndServe()
err = http.Serve(listener, r)
urlFilePath := filepath.Join(config.CommonInfo.RuntimePath, "casaos.url")
err = file.CreateFileAndWriteContent(urlFilePath, "http://"+listener.Addr().String())
if err != nil {
loger.Error("Management service is listening...",
zap.Any("address", listener.Addr().String()),
zap.Any("filepath", urlFilePath),
)
}
if supported, err := daemon.SdNotify(false, daemon.SdNotifyReady); err != nil {
loger.Error("Failed to notify systemd that casaos main service is ready", zap.Any("error", err))
} else if supported {
loger.Info("Notified systemd that casaos main service is ready")
} else {
loger.Info("This process is not running as a systemd service.")
}
s := &http.Server{
Handler: r,
ReadHeaderTimeout: 5 * time.Second, // fix G112: Potential slowloris attack (see https://github.com/securego/gosec)
}
err = s.Serve(listener) // not using http.serve() to fix G114: Use of net/http serve function that has no support for setting timeouts (see https://github.com/securego/gosec)
if err != nil {
panic(err)
}

View file

@ -1,62 +0,0 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2021-10-08 10:29:08
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-22 11:06:07
* @FilePath: /CasaOS/middleware/gin.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package middleware
import (
"fmt"
"net/http"
"strings"
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
func Cors() gin.HandlerFunc {
return func(c *gin.Context) {
method := c.Request.Method
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
//允许跨域设置可以返回其他子段,可以自定义字段
c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,Language,Content-Type,Access-Control-Allow-Origin,Access-Control-Allow-Headers,Access-Control-Allow-Methods,Connection,Host,Origin,Referer,User-Agent,X-Requested-With")
// 允许浏览器(客户端)可以解析的头部 (重要)
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers")
//c.Writer.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type, Content-Length, X-CSRF-Token, Token, session, Origin, Host, Connection, Accept-Encoding, Accept-Language, X-Requested-With")
//设置缓存时间
c.Header("Access-Control-Max-Age", "172800")
c.Header("Access-Control-Allow-Credentials", "true")
c.Set("Content-Type", "application/json")
//}
//允许类型校验
if method == "OPTIONS" {
c.JSON(http.StatusOK, "ok!")
}
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
}()
c.Next()
}
}
func WriteLog() gin.HandlerFunc {
return func(c *gin.Context) {
if !strings.Contains(c.Request.URL.String(), "password") {
loger.Info("request:", zap.Any("path", c.Request.URL.String()), zap.Any("param", c.Params), zap.Any("query", c.Request.URL.Query()), zap.Any("method", c.Request.Method))
c.Next()
}
}
}

View file

@ -1,98 +0,0 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-07-13 10:43:45
* @LastEditors: LinkLeong
* @LastEditTime: 2022-08-03 14:45:35
* @FilePath: /CasaOS/model/disk.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package model
type LSBLKModel struct {
Name string `json:"name"`
FsType string `json:"fstype"`
Size uint64 `json:"size"`
FSSize string `json:"fssize"`
Path string `json:"path"`
Model string `json:"model"` //设备标识符
RM bool `json:"rm"` //是否为可移动设备
RO bool `json:"ro"` //是否为只读设备
State string `json:"state"`
PhySec int `json:"phy-sec"` //物理扇区大小
Type string `json:"type"`
Vendor string `json:"vendor"` //供应商
Rev string `json:"rev"` //修订版本
FSAvail string `json:"fsavail"` //可用空间
FSUse string `json:"fsuse%"` //已用百分比
MountPoint string `json:"mountpoint"`
Format string `json:"format"`
Health string `json:"health"`
HotPlug bool `json:"hotplug"`
UUID string `json:"uuid"`
FSUsed string `json:"fsused"`
Temperature int `json:"temperature"`
Tran string `json:"tran"`
MinIO uint64 `json:"min-io"`
UsedPercent float64 `json:"used_percent"`
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)
DiskType string `json:"disk_type"`
EndSector uint64 `json:"end_sector,omitempty"`
}
type Drive struct {
Name string `json:"name"`
Size uint64 `json:"size"`
Model string `json:"model"`
Health string `json:"health"`
Temperature int `json:"temperature"`
DiskType string `json:"disk_type"`
NeedFormat bool `json:"need_format"`
Serial string `json:"serial"`
Path string `json:"path"`
ChildrenNumber int `json:"children_number"`
}
type DriveUSB struct {
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 {
MountPoint string `json:"mount_point"`
Size string `json:"size"`
Avail string `json:"avail"` //可用空间
Type string `json:"type"`
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 {
Size uint64 `json:"size"`
Avail uint64 `json:"avail"` //可用空间
Health bool `json:"health"`
Used uint64 `json:"used"`
}

View file

@ -16,3 +16,9 @@ type DockerStatsModel struct {
Data interface{} `json:"data"`
Previous interface{} `json:"previous"`
}
// reference - https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-configuration-file
type DockerDaemonConfigurationModel struct {
// e.g. `/var/lib/docker`
Root string `json:"data-root,omitempty"`
}

View file

@ -1 +0,0 @@
package receive

View file

@ -12,12 +12,12 @@ package model
import "time"
//系统配置
// 系统配置
type SysInfoModel struct {
Name string //系统名称
}
//服务配置
// 服务配置
type ServerModel struct {
HttpPort string
RunMode string
@ -26,9 +26,10 @@ type ServerModel struct {
Token string
USBAutoMount string
SocketPort string
UpdateUrl string
}
//服务配置
// 服务配置
type APPModel struct {
LogPath string
LogSaveName string
@ -40,20 +41,19 @@ type APPModel struct {
DateFormat string
DBPath string
ShellPath string
TempPath string
}
type CommonModel struct {
RuntimePath string
}
//公共返回模型
// 公共返回模型
type Result struct {
Success int `json:"success" example:"200"`
Message string `json:"message" example:"ok"`
Data interface{} `json:"data" example:"返回结果"`
}
//redis配置文件
// redis配置文件
type RedisModel struct {
Host string
Password string

View file

@ -23,17 +23,17 @@ import (
"github.com/go-ini/ini"
)
//系统配置
// 系统配置
var SysInfo = &model.SysInfoModel{}
//用户相关
// 用户相关
var AppInfo = &model.APPModel{}
var CommonInfo = &model.CommonModel{}
//var RedisInfo = &model.RedisModel{}
//server相关
// server相关
var ServerInfo = &model.ServerModel{}
var SystemConfigInfo = &model.SystemConfig{}
@ -44,7 +44,7 @@ var FileSettingInfo = &model.FileSetting{}
var Cfg *ini.File
//初始化设置,获取系统的部分信息。
// 初始化设置,获取系统的部分信息。
func InitSetup(config string) {
var configDir = USERCONFIGURL
@ -86,9 +86,6 @@ func InitSetup(config string) {
if len(AppInfo.UserDataPath) == 0 {
AppInfo.UserDataPath = "/var/lib/casaos/conf"
}
if len(AppInfo.TempPath) == 0 {
AppInfo.TempPath = "/var/lib/casaos/temp"
}
if len(CommonInfo.RuntimePath) == 0 {
CommonInfo.RuntimePath = "/var/run/casaos"
}
@ -97,7 +94,7 @@ func InitSetup(config string) {
}
//映射
// 映射
func mapTo(section string, v interface{}) {
err := Cfg.Section(section).MapTo(v)
if err != nil {

View file

@ -1,32 +0,0 @@
package config
import (
"runtime"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
)
//检查目录是否存在
func mkdirDATAAll() {
sysType := runtime.GOOS
var dirArray []string
if sysType == "linux" {
dirArray = []string{"/DATA/AppData", "/DATA/Documents", "/DATA/Downloads", "/DATA/Gallery", "/DATA/Media/Movies", "/DATA/Media/TV Shows", "/DATA/Media/Music"}
}
if sysType == "windows" {
dirArray = []string{"C:\\CasaOS\\DATA\\AppData", "C:\\CasaOS\\DATA\\Documents", "C:\\CasaOS\\DATA\\Downloads", "C:\\CasaOS\\DATA\\Gallery", "C:\\CasaOS\\DATA\\Media/Movies", "C:\\CasaOS\\DATA\\Media\\TV Shows", "C:\\CasaOS\\DATA\\Media\\Music"}
}
if sysType == "darwin" {
dirArray = []string{"./CasaOS/DATA/AppData", "./CasaOS/DATA/Documents", "./CasaOS/DATA/Downloads", "./CasaOS/DATA/Gallery", "./CasaOS/DATA/Media/Movies", "./CasaOS/DATA/Media/TV Shows", "./CasaOS/DATA/Media/Music"}
}
for _, v := range dirArray {
file.IsNotExistMkDir(v)
}
}
func UpdateSetup() {
mkdirDATAAll()
}

View file

@ -15,7 +15,6 @@ import (
)
func NewSshClient(user, password string, port string) (*ssh.Client, error) {
// connet to ssh
// addr = fmt.Sprintf("%s:%d", host, port)
@ -23,10 +22,10 @@ func NewSshClient(user, password string, port string) (*ssh.Client, error) {
Timeout: time.Second * 5,
User: user,
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
//HostKeyCallback: ,
//HostKeyCallback: hostKeyCallBackFunc(h.Host),
// HostKeyCallback: ,
// HostKeyCallback: hostKeyCallBackFunc(h.Host),
}
//if h.Type == "password" {
// if h.Type == "password" {
config.Auth = []ssh.AuthMethod{ssh.Password(password)}
//} else {
// config.Auth = []ssh.AuthMethod{publicKeyAuthFunc(h.Key)}
@ -90,11 +89,11 @@ func (w *wsBufferWriter) Write(p []byte) (int, error) {
defer w.mu.Unlock()
return w.buffer.Write(p)
}
func (s *SshConn) Close() {
if s.Session != nil {
s.Session.Close()
}
}
const (
@ -102,16 +101,15 @@ const (
wsMsgResize = "resize"
)
//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
// ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
//tells other go routine quit
// tells other go routine quit
username := ""
for {
//read websocket msg
// read websocket msg
_, wsData, err := wsConn.ReadMessage()
if err != nil {
return ""
}
@ -125,8 +123,8 @@ func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
//}
switch msgObj.Type {
case wsMsgCmd:
//handle xterm.js stdin
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
// handle xterm.js stdin
// decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
decodeBytes := []byte(msgObj.Cmd)
if msgObj.Cmd == "\u007f" {
if len(username) == 0 {
@ -144,7 +142,7 @@ func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
if err := wsConn.WriteMessage(websocket.TextMessage, decodeBytes); err != nil {
logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
}
//write input cmd to log buffer
// write input cmd to log buffer
if _, err := logBuff.Write(decodeBytes); err != nil {
logrus.WithError(err).Error("write received cmd into log buffer failed")
}
@ -154,11 +152,11 @@ func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
}
func ReceiveWsMsgPassword(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
//tells other go routine quit
// tells other go routine quit
password := ""
for {
//read websocket msg
// read websocket msg
_, wsData, err := wsConn.ReadMessage()
if err != nil {
logrus.WithError(err).Error("reading webSocket message failed")
@ -175,8 +173,8 @@ func ReceiveWsMsgPassword(wsConn *websocket.Conn, logBuff *bytes.Buffer) string
//}
switch msgObj.Type {
case wsMsgCmd:
//handle xterm.js stdin
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
// handle xterm.js stdin
// decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
if msgObj.Cmd == "\r" {
return password
}
@ -194,16 +192,16 @@ func ReceiveWsMsgPassword(wsConn *websocket.Conn, logBuff *bytes.Buffer) string
}
}
//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
// ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffer, exitCh chan bool) {
//tells other go routine quit
// tells other go routine quit
defer setQuit(exitCh)
for {
select {
case <-exitCh:
return
default:
//read websocket msg
// read websocket msg
_, wsData, err := wsConn.ReadMessage()
if err != nil {
logrus.WithError(err).Error("reading webSocket message failed")
@ -227,15 +225,15 @@ func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffe
switch msgObj.Type {
case wsMsgResize:
//handle xterm.js size change
// handle xterm.js size change
if msgObj.Cols > 0 && msgObj.Rows > 0 {
if err := ssConn.Session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil {
logrus.WithError(err).Error("ssh pty change windows size failed")
}
}
case wsMsgCmd:
//handle xterm.js stdin
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
// handle xterm.js stdin
// decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
decodeBytes := []byte(msgObj.Cmd)
if err != nil {
logrus.WithError(err).Error("websock cmd string base64 decoding failed")
@ -243,7 +241,7 @@ func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffe
if _, err := ssConn.StdinPipe.Write(decodeBytes); err != nil {
logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
}
//write input cmd to log buffer
// write input cmd to log buffer
if _, err := logBuff.Write(decodeBytes); err != nil {
logrus.WithError(err).Error("write received cmd into log buffer failed")
}
@ -253,17 +251,17 @@ func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffe
}
func (ssConn *SshConn) SendComboOutput(wsConn *websocket.Conn, exitCh chan bool) {
//tells other go routine quit
//defer setQuit(exitCh)
// tells other go routine quit
// defer setQuit(exitCh)
//every 120ms write combine output bytes into websocket response
// every 120ms write combine output bytes into websocket response
tick := time.NewTicker(time.Millisecond * time.Duration(120))
//for range time.Tick(120 * time.Millisecond){}
// for range time.Tick(120 * time.Millisecond){}
defer tick.Stop()
for {
select {
case <-tick.C:
//write combine output bytes into websocket response
// write combine output bytes into websocket response
if err := flushComboOutput(ssConn.ComboOutput, wsConn); err != nil {
logrus.WithError(err).Error("ssh sending combo output to webSocket failed")
return
@ -273,6 +271,7 @@ func (ssConn *SshConn) SendComboOutput(wsConn *websocket.Conn, exitCh chan bool)
}
}
}
func flushComboOutput(w *wsBufferWriter, wsConn *websocket.Conn) error {
if w.buffer.Len() != 0 {
err := wsConn.WriteMessage(websocket.TextMessage, w.buffer.Bytes())
@ -284,16 +283,16 @@ func flushComboOutput(w *wsBufferWriter, wsConn *websocket.Conn) error {
return nil
}
//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
// ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exitCh chan bool) {
//tells other go routine quit
// tells other go routine quit
defer setQuit(exitCh)
for {
select {
case <-exitCh:
return
default:
//read websocket msg
// read websocket msg
_, wsData, err := wsConn.ReadMessage()
if err != nil {
logrus.WithError(err).Error("reading webSocket message failed")
@ -317,15 +316,15 @@ func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exit
switch msgObj.Type {
case wsMsgResize:
//handle xterm.js size change
// handle xterm.js size change
if msgObj.Cols > 0 && msgObj.Rows > 0 {
if err := ssConn.Session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil {
logrus.WithError(err).Error("ssh pty change windows size failed")
}
}
case wsMsgCmd:
//handle xterm.js stdin
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
// handle xterm.js stdin
// decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
decodeBytes := []byte(msgObj.Cmd)
if err != nil {
logrus.WithError(err).Error("websock cmd string base64 decoding failed")
@ -333,7 +332,7 @@ func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exit
if _, err := ssConn.StdinPipe.Write(decodeBytes); err != nil {
logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
}
//write input cmd to log buffer
// write input cmd to log buffer
if _, err := logBuff.Write(decodeBytes); err != nil {
logrus.WithError(err).Error("write received cmd into log buffer failed")
}
@ -341,6 +340,7 @@ func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exit
}
}
}
func (ssConn *SshConn) SessionWait(quitChan chan bool) {
if err := ssConn.Session.Wait(); err != nil {
logrus.WithError(err).Error("ssh session wait failed")
@ -395,7 +395,7 @@ func WsReaderCopy(reader *websocket.Conn, writer io.Writer) {
if err = json2.Unmarshal(p, &msgObj); err != nil {
writer.Write(p)
} else if msgObj.Type == wsMsgResize {
//writer.Write([]byte("stty rows " + strconv.Itoa(msgObj.Rows) + " && stty cols " + strconv.Itoa(msgObj.Cols) + " \r"))
// writer.Write([]byte("stty rows " + strconv.Itoa(msgObj.Rows) + " && stty cols " + strconv.Itoa(msgObj.Cols) + " \r"))
}
}
}

View file

@ -43,7 +43,7 @@ func GetDb(dbPath string) *gorm.DB {
}
gdb = db
err = db.AutoMigrate(&model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{}, model2.SharesDBModel{}, model2.ConnectionsDBModel{})
err = db.AutoMigrate(&model2.AppNotify{}, &model2.AppListDBModel{}, 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")

View file

@ -35,8 +35,8 @@ func ExecResultStrArray(cmdStr string) []string {
fmt.Println(err)
return nil
}
//str, err := ioutil.ReadAll(stdout)
var networklist = []string{}
// str, err := ioutil.ReadAll(stdout)
networklist := []string{}
outputBuf := bufio.NewReader(stdout)
for {
output, _, err := outputBuf.ReadLine()
@ -54,6 +54,8 @@ func ExecResultStrArray(cmdStr string) []string {
func ExecResultStr(cmdStr string) string {
cmd := exec.Command("/bin/bash", "-c", cmdStr)
println(cmd.String())
stdout, err := cmd.StdoutPipe()
if err != nil {
fmt.Println(err)
@ -73,7 +75,7 @@ func ExecResultStr(cmdStr string) string {
return string(str)
}
//执行 lsblk 命令
// 执行 lsblk 命令
func ExecLSBLK() []byte {
output, err := exec.Command("lsblk", "-O", "-J", "-b").Output()
if err != nil {
@ -83,7 +85,7 @@ func ExecLSBLK() []byte {
return output
}
//执行 lsblk 命令
// 执行 lsblk 命令
func ExecLSBLKByPath(path string) []byte {
output, err := exec.Command("lsblk", path, "-O", "-J", "-b").Output()
if err != nil {
@ -93,7 +95,7 @@ func ExecLSBLKByPath(path string) []byte {
return output
}
//exec smart
// exec smart
func ExecSmartCTLByPath(path string) []byte {
timeout := 3
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
@ -107,6 +109,5 @@ func ExecSmartCTLByPath(path string) []byte {
}
func ExecEnabledSMART(path string) {
exec.Command("smartctl", "-s on", path).Output()
}

View file

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"io"
"io/fs"
"io/ioutil"
"log"
"mime/multipart"
@ -60,7 +61,7 @@ func MkDir(src string) error {
if err != nil {
return err
}
os.Chmod(src, 0777)
os.Chmod(src, 0o777)
return nil
}
@ -103,7 +104,7 @@ func MustOpen(fileName, filePath string) (*os.File, error) {
return nil, fmt.Errorf("file.IsNotExistMkDir src: %s, err: %v", src, err)
}
f, err := Open(src+fileName, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
f, err := Open(src+fileName, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0o644)
if err != nil {
return nil, fmt.Errorf("Fail to OpenFile :%v", err)
}
@ -113,7 +114,7 @@ func MustOpen(fileName, filePath string) (*os.File, error) {
// 判断所给路径文件/文件夹是否存在
func Exists(path string) bool {
_, err := os.Stat(path) //os.Stat获取文件信息
_, err := os.Stat(path) // os.Stat获取文件信息
if err != nil {
if os.IsExist(err) {
return true
@ -147,7 +148,7 @@ func CreateFile(path string) error {
}
func CreateFileAndWriteContent(path string, content string) error {
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0666)
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0o666)
if err != nil {
return err
}
@ -163,7 +164,7 @@ func CreateFileAndWriteContent(path string, content string) error {
// IsNotExistMkDir create a directory if it does not exist
func IsNotExistCreateFile(src string) error {
if notExist := CheckNotExist(src); notExist == true {
if notExist := CheckNotExist(src); notExist {
if err := CreateFile(src); err != nil {
return err
}
@ -267,7 +268,7 @@ func CopySingleFile(src, dst, style string) error {
return os.Chmod(dst, srcinfo.Mode())
}
//Check for duplicate file names
// Check for duplicate file names
func GetNoDuplicateFileName(fullPath string) string {
path, fileName := filepath.Split(fullPath)
fileSuffix := path2.Ext(fileName)
@ -293,7 +294,7 @@ func CopyDir(src string, dst string, style string) error {
}
return nil
}
//dstPath := dst
// dstPath := dst
lastPath := src[strings.LastIndex(src, "/")+1:]
dst += "/" + lastPath
// for i := 0; Exists(dst); i++ {
@ -314,7 +315,7 @@ func CopyDir(src string, dst string, style string) error {
}
for _, fd := range fds {
srcfp := path.Join(src, fd.Name())
dstfp := dst //path.Join(dst, fd.Name())
dstfp := dst // path.Join(dst, fd.Name())
if fd.IsDir() {
if err = CopyDir(srcfp, dstfp, style); err != nil {
@ -336,10 +337,17 @@ func WriteToPath(data []byte, path, name string) error {
} else {
fullPath += "/" + name
}
IsNotExistCreateFile(fullPath)
return WriteToFullPath(data, fullPath, 0o666)
}
func WriteToFullPath(data []byte, fullPath string, perm fs.FileMode) error {
if err := IsNotExistCreateFile(fullPath); err != nil {
return err
}
file, err := os.OpenFile(fullPath,
os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
0666,
perm,
)
if err != nil {
return err
@ -350,26 +358,31 @@ func WriteToPath(data []byte, path, name string) error {
return err
}
//最终拼接
// 最终拼接
func SpliceFiles(dir, path string, length int, startPoint int) error {
fullPath := path
IsNotExistCreateFile(fullPath)
if err := IsNotExistCreateFile(fullPath); err != nil {
return err
}
file, _ := os.OpenFile(fullPath,
os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
0666,
0o666,
)
defer file.Close()
bufferedWriter := bufio.NewWriter(file)
for i := 0; i < length+startPoint; i++ {
// todo: here should have a goroutine to remove each partial file after it is read, to save disk space
for i := 0; i < length+startPoint-1; i++ {
data, err := ioutil.ReadFile(dir + "/" + strconv.Itoa(i+startPoint))
if err != nil {
return err
}
_, err = bufferedWriter.Write(data)
if err != nil {
if _, err := bufferedWriter.Write(data); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster write
return err
}
}
@ -380,7 +393,6 @@ func SpliceFiles(dir, path string, length int, startPoint int) error {
}
func GetCompressionAlgorithm(t string) (string, archiver.Writer, error) {
switch t {
case "zip", "":
return ".zip", archiver.NewZip(), nil
@ -400,8 +412,8 @@ func GetCompressionAlgorithm(t string) (string, archiver.Writer, error) {
return "", nil, errors.New("format not implemented")
}
}
func AddFile(ar archiver.Writer, path, commonPath string) error {
func AddFile(ar archiver.Writer, path, commonPath string) error {
info, err := os.Stat(path)
if err != nil {
return err
@ -447,6 +459,7 @@ func AddFile(ar archiver.Writer, path, commonPath string) error {
return nil
}
func CommonPrefix(sep byte, paths ...string) string {
// Handle special cases.
switch len(paths) {
@ -513,7 +526,7 @@ func GetFileOrDirSize(path string) (int64, error) {
return fileInfo.Size(), nil
}
//getFileSize get file size by path(B)
// getFileSize get file size by path(B)
func DirSizeB(path string) (int64, error) {
var size int64
err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {

View file

@ -3,65 +3,19 @@ package route
import (
"fmt"
"os"
"strconv"
"strings"
"time"
"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/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"go.uber.org/zap"
)
func InitFunction() {
CheckSerialDiskMount()
go InitNetworkMount()
}
func CheckSerialDiskMount() {
// check mount point
dbList := service.MyService.Disk().GetSerialAll()
list := service.MyService.Disk().LSBLK(true)
mountPoint := make(map[string]string, len(dbList))
//remount
for _, v := range dbList {
mountPoint[v.UUID] = v.MountPoint
}
for _, v := range list {
command.ExecEnabledSMART(v.Path)
if v.Children != nil {
for _, h := range v.Children {
//if len(h.MountPoint) == 0 && len(v.Children) == 1 && h.FsType == "ext4" {
if m, ok := mountPoint[h.UUID]; ok {
//mount point check
volume := m
if !file.CheckNotExist(m) {
for i := 0; file.CheckNotExist(volume); i++ {
volume = m + strconv.Itoa(i+1)
}
}
service.MyService.Disk().MountDisk(h.Path, volume)
if volume != m {
ms := model2.SerialDisk{}
ms.UUID = v.UUID
ms.MountPoint = volume
service.MyService.Disk().UpdateMountPoint(ms)
}
}
//}
}
}
}
service.MyService.Disk().RemoveLSBLKCache()
command.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;AutoRemoveUnuseDir")
}
func InitNetworkMount() {
time.Sleep(time.Second * 10)
connections := service.MyService.Connections().GetConnectionsList()

View file

@ -14,20 +14,12 @@
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() {
@ -61,104 +53,6 @@ func SendMemBySocket() {
service.MyService.Notify().SendMemInfoBySocket(service.MyService.System().GetMemInfo())
}
func SendDiskBySocket() {
list := service.MyService.Disk().LSBLK(true)
summary := model.Summary{}
healthy := true
findSystem := 0
for i := 0; i < len(list); i++ {
if len(list[i].Children) > 0 && findSystem == 0 {
for j := 0; j < len(list[i].Children); j++ {
if len(list[i].Children[j].Children) > 0 {
for _, v := range list[i].Children[j].Children {
if v.MountPoint == "/" {
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
summary.Size += s
summary.Avail += a
summary.Used += u
findSystem = 1
break
}
}
} else {
if list[i].Children[j].MountPoint == "/" {
s, _ := strconv.ParseUint(list[i].Children[j].FSSize, 10, 64)
a, _ := strconv.ParseUint(list[i].Children[j].FSAvail, 10, 64)
u, _ := strconv.ParseUint(list[i].Children[j].FSUsed, 10, 64)
summary.Size += s
summary.Avail += a
summary.Used += u
findSystem = 1
break
}
}
}
}
if findSystem == 1 {
findSystem += 1
continue
}
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") {
temp := service.MyService.Disk().SmartCTL(list[i].Path)
if reflect.DeepEqual(temp, model.SmartctlA{}) {
healthy = true
} else {
healthy = temp.SmartStatus.Passed
}
//list[i].Temperature = temp.Temperature.Current
if len(list[i].Children) > 0 {
for _, v := range list[i].Children {
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
summary.Size += s
summary.Avail += a
summary.Used += u
}
}
}
}
summary.Health = healthy
service.MyService.Notify().SendDiskInfoBySocket(summary)
}
func SendUSBBySocket() {
usbList := service.MyService.Disk().LSBLK(false)
usb := []model.DriveUSB{}
for _, v := range usbList {
if v.Tran == "usb" {
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)
}
func SendAllHardwareStatusBySocket() {
netList := service.MyService.System().GetNetInfo()
@ -183,131 +77,44 @@ func SendAllHardwareStatusBySocket() {
cpuData["temperature"] = service.MyService.System().GetCPUTemperature()
cpuData["power"] = service.MyService.System().GetCPUPower()
list := service.MyService.Disk().LSBLK(true)
summary := model.Summary{}
healthy := true
findSystem := 0
for i := 0; i < len(list); i++ {
if len(list[i].Children) > 0 && findSystem == 0 {
for j := 0; j < len(list[i].Children); j++ {
if len(list[i].Children[j].Children) > 0 {
for _, v := range list[i].Children[j].Children {
if v.MountPoint == "/" {
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
summary.Size += s
summary.Avail += a
summary.Used += u
findSystem = 1
break
}
}
} else {
if list[i].Children[j].MountPoint == "/" {
s, _ := strconv.ParseUint(list[i].Children[j].FSSize, 10, 64)
a, _ := strconv.ParseUint(list[i].Children[j].FSAvail, 10, 64)
u, _ := strconv.ParseUint(list[i].Children[j].FSUsed, 10, 64)
summary.Size += s
summary.Avail += a
summary.Used += u
findSystem = 1
break
}
}
}
}
if findSystem == 1 {
findSystem += 1
continue
}
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") {
temp := service.MyService.Disk().SmartCTL(list[i].Path)
if reflect.DeepEqual(temp, model.SmartctlA{}) {
healthy = true
} else {
healthy = temp.SmartStatus.Passed
}
if len(list[i].Children) > 0 {
for _, v := range list[i].Children {
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
summary.Size += s
summary.Avail += a
summary.Used += u
}
}
}
}
summary.Health = healthy
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)
}
}
}
memInfo := service.MyService.System().GetMemInfo()
service.MyService.Notify().SendAllHardwareStatusBySocket(summary, usb, memInfo, cpuData, newNet)
service.MyService.Notify().SendAllHardwareStatusBySocket(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()
// func MonitoryUSB() {
// var matcher netlink.Matcher
queue := make(chan netlink.UEvent)
errors := make(chan error)
quit := conn.Monitor(queue, errors, 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()
signals := make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
go func() {
<-signals
close(quit)
os.Exit(0)
}()
// queue := make(chan netlink.UEvent)
// errors := make(chan error)
// quit := conn.Monitor(queue, errors, matcher)
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))
}
}
// 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))
// }
// }
// }

View file

@ -1,8 +1,10 @@
package route
import (
jwt2 "github.com/IceWhaleTech/CasaOS-Common/utils/jwt"
"github.com/IceWhaleTech/CasaOS/middleware"
"os"
"github.com/IceWhaleTech/CasaOS-Common/middleware"
"github.com/IceWhaleTech/CasaOS-Common/utils/jwt"
"github.com/IceWhaleTech/CasaOS/pkg/config"
v1 "github.com/IceWhaleTech/CasaOS/route/v1"
@ -11,13 +13,22 @@ import (
)
func InitRouter() *gin.Engine {
ginMode := gin.ReleaseMode
if config.ServerInfo.RunMode != "" {
ginMode = config.ServerInfo.RunMode
}
if os.Getenv(gin.EnvGinMode) != "" {
ginMode = os.Getenv(gin.EnvGinMode)
}
gin.SetMode(ginMode)
r := gin.Default()
r := gin.New()
r.Use(gin.Recovery())
r.Use(middleware.Cors())
r.Use(middleware.WriteLog())
r.Use(gzip.Gzip(gzip.DefaultCompression))
gin.SetMode(config.ServerInfo.RunMode)
if ginMode != gin.ReleaseMode {
r.Use(middleware.WriteLog())
}
// r.StaticFS("/ui", http.FS(web.Static))
// r.GET("/", WebUIHome)
@ -35,15 +46,17 @@ func InitRouter() *gin.Engine {
// r.GET("/v1/users/image", v1.GetUserImage)
// r.GET("/v1/users/status", v1.GetUserStatus) //init/check
//r.GET("/v1/guide/check", v1.GetGuideCheck) // /v1/sys/guide_check
// r.GET("/v1/guide/check", v1.GetGuideCheck) // /v1/sys/guide_check
r.GET("/v1/sys/debug", v1.GetSystemConfigDebug) // //debug
r.GET("/v1/sys/socket-port", v1.GetSystemSocketPort) //sys/socket_port
r.GET("/v1/sys/version/check", v1.GetSystemCheckVersion)
r.GET("/ping", func(ctx *gin.Context) {
ctx.String(200, "pong")
})
v1Group := r.Group("/v1")
v1Group.Use(jwt2.JWT())
v1Group.Use(jwt.ExceptLocalhost())
{
// v1UsersGroup := v1Group.Group("/users")
// v1UsersGroup.Use()
@ -71,32 +84,35 @@ func InitRouter() *gin.Engine {
v1AppsGroup := v1Group.Group("/apps")
v1AppsGroup.Use()
{
v1AppsGroup.GET("", v1.AppList) //list
v1AppsGroup.GET("", v1.AppList) // list
v1AppsGroup.GET("/:id", v1.AppInfo)
}
v1ContainerGroup := v1Group.Group("/container")
v1ContainerGroup.Use()
{
v1ContainerGroup.GET("", v1.MyAppList) ///my/list
v1ContainerGroup.GET("/usage", v1.AppUsageList)
v1ContainerGroup.GET("/:id", v1.ContainerUpdateInfo) ///update/:id/info
v1ContainerGroup.GET("/:id/logs", v1.ContainerLog) // /app/logs/:id
v1ContainerGroup.GET("/networks", v1.GetDockerNetworks) //app/install/config
v1ContainerGroup.GET("/networks", v1.GetDockerNetworks) // app/install/config
v1ContainerGroup.GET("/:id/state", v1.GetContainerState) //app/state/:id ?state=install_progress
v1ContainerGroup.GET("/:id/state", v1.GetContainerState) // app/state/:id ?state=install_progress
// there are problems, temporarily do not deal with
v1ContainerGroup.GET("/:id/terminal", v1.DockerTerminal) //app/terminal/:id
v1ContainerGroup.POST("", v1.InstallApp) //app/install
//v1ContainerGroup.GET("/:id", v1.ContainerInfo) // /app/info/:id
v1ContainerGroup.GET("/:id/terminal", v1.DockerTerminal) // app/terminal/:id
v1ContainerGroup.POST("", v1.InstallApp) // app/install
// v1ContainerGroup.GET("/:id", v1.ContainerInfo) // /app/info/:id
v1ContainerGroup.PUT("/:id", v1.UpdateSetting) ///update/:id/setting
v1ContainerGroup.PUT("/:id/state", v1.ChangAppState) // /app/state/:id
v1ContainerGroup.DELETE("/:id", v1.UnInstallApp) //app/uninstall/:id
//Not used
v1ContainerGroup.DELETE("/:id", v1.UnInstallApp) // app/uninstall/:id
// Not used
v1ContainerGroup.PUT("/:id/latest", v1.PutAppUpdate)
//Not used
// Not used
v1ContainerGroup.POST("/share", v1.ShareAppFile)
v1ContainerGroup.GET("/info", v1.GetDockerDaemonConfiguration)
v1ContainerGroup.PUT("/info", v1.PutDockerDaemonConfiguration)
}
v1AppCategoriesGroup := v1Group.Group("/app-categories")
@ -108,19 +124,19 @@ func InitRouter() *gin.Engine {
v1SysGroup := v1Group.Group("/sys")
v1SysGroup.Use()
{
v1SysGroup.GET("/version", v1.GetSystemCheckVersion) //version/check
v1SysGroup.GET("/version", v1.GetSystemCheckVersion) // version/check
v1SysGroup.POST("/update", v1.SystemUpdate)
v1SysGroup.GET("/hardware", v1.GetSystemHardwareInfo) //hardware/info
v1SysGroup.GET("/hardware", v1.GetSystemHardwareInfo) // hardware/info
v1SysGroup.GET("/wsssh", v1.WsSsh)
v1SysGroup.POST("/ssh-login", v1.PostSshLogin)
//v1SysGroup.GET("/config", v1.GetSystemConfig) //delete
//v1SysGroup.POST("/config", v1.PostSetSystemConfig)
v1SysGroup.GET("/logs", v1.GetCasaOSErrorLogs) //error/logs
//v1SysGroup.GET("/widget/config", v1.GetWidgetConfig)//delete
//v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig)//delete
// v1SysGroup.GET("/config", v1.GetSystemConfig) //delete
// v1SysGroup.POST("/config", v1.PostSetSystemConfig)
v1SysGroup.GET("/logs", v1.GetCasaOSErrorLogs) // error/logs
// v1SysGroup.GET("/widget/config", v1.GetWidgetConfig)//delete
// v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig)//delete
v1SysGroup.POST("/stop", v1.PostKillCasaOS)
@ -130,37 +146,34 @@ func InitRouter() *gin.Engine {
// v1SysGroup.GET("/disk", v1.GetSystemDiskInfo)
// v1SysGroup.GET("/network", v1.GetSystemNetInfo)
v1SysGroup.PUT("/usb-auto-mount", v1.PutSystemUSBAutoMount) ///sys/usb/:status
v1SysGroup.GET("/usb-auto-mount", v1.GetSystemUSBAutoMount) ///sys/usb/status
v1SysGroup.GET("/server-info", nil)
v1SysGroup.PUT("/server-info", nil)
v1SysGroup.GET("/apps-state", v1.GetSystemAppsStatus)
//v1SysGroup.GET("/port", v1.GetCasaOSPort)
//v1SysGroup.PUT("/port", v1.PutCasaOSPort)
// v1SysGroup.GET("/port", v1.GetCasaOSPort)
// v1SysGroup.PUT("/port", v1.PutCasaOSPort)
v1SysGroup.GET("/proxy", v1.GetSystemProxy)
}
v1PortGroup := v1Group.Group("/port")
v1PortGroup.Use()
{
v1PortGroup.GET("/", v1.GetPort) //app/port
v1PortGroup.GET("/state/:port", v1.PortCheck) //app/check/:port
v1PortGroup.GET("/", v1.GetPort) // app/port
v1PortGroup.GET("/state/:port", v1.PortCheck) // app/check/:port
}
v1FileGroup := v1Group.Group("/file")
v1FileGroup.Use()
{
v1FileGroup.GET("", v1.GetDownloadSingleFile) //download/:path
v1FileGroup.GET("", v1.GetDownloadSingleFile) // download/:path
v1FileGroup.POST("", v1.PostCreateFile)
v1FileGroup.PUT("", v1.PutFileContent)
v1FileGroup.PUT("/name", v1.RenamePath)
//file/rename
v1FileGroup.GET("/content", v1.GetFilerContent) //file/read
// file/rename
v1FileGroup.GET("/content", v1.GetFilerContent) // file/read
//File uploads need to be handled separately, and will not be modified here
// File uploads need to be handled separately, and will not be modified here
v1FileGroup.POST("/upload", v1.PostFileUpload)
v1FileGroup.GET("/upload", v1.GetFileUpload)
//v1FileGroup.GET("/download", v1.UserFileDownloadCommonService)
// v1FileGroup.GET("/download", v1.UserFileDownloadCommonService)
}
v1FolderGroup := v1Group.Group("/folder")
v1FolderGroup.Use()
@ -173,9 +186,9 @@ func InitRouter() *gin.Engine {
v1BatchGroup.Use()
{
v1BatchGroup.DELETE("", v1.DeleteFile) //file/delete
v1BatchGroup.DELETE("", v1.DeleteFile) // file/delete
v1BatchGroup.DELETE("/:id/task", v1.DeleteOperateFileOrDir)
v1BatchGroup.POST("/task", v1.PostOperateFileOrDir) //file/operate
v1BatchGroup.POST("/task", v1.PostOperateFileOrDir) // file/operate
v1BatchGroup.GET("", v1.GetDownloadFile)
}
v1ImageGroup := v1Group.Group("/image")
@ -183,42 +196,6 @@ func InitRouter() *gin.Engine {
{
v1ImageGroup.GET("", v1.GetFileImage)
}
v1DisksGroup := v1Group.Group("/disks")
v1DisksGroup.Use()
{
//v1DiskGroup.GET("/check", v1.GetDiskCheck) //delete
//v1DisksGroup.GET("", v1.GetDiskInfo)
//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)
// //mount SATA disk
// v1DiskGroup.POST("/mount", v1.PostMountDisk)
// //umount sata disk
// v1DiskGroup.POST("/umount", v1.PostDiskUmount)
//v1DiskGroup.GET("/type", v1.FormatDiskType)//delete
v1DisksGroup.DELETE("/part", v1.RemovePartition) //disk/delpart
}
v1StorageGroup := v1Group.Group("/storage")
v1StorageGroup.Use()
{
v1StorageGroup.POST("", v1.PostDiskAddPartition)
v1StorageGroup.PUT("", v1.PostDiskFormat)
v1StorageGroup.DELETE("", v1.PostDiskUmount)
v1StorageGroup.GET("", v1.GetStorageList)
}
v1SambaGroup := v1Group.Group("/samba")
v1SambaGroup.Use()
{
@ -238,6 +215,13 @@ func InitRouter() *gin.Engine {
v1SharesGroup.GET("/status", v1.GetSambaStatus)
}
}
v1NotifyGroup := v1Group.Group("/notify")
v1NotifyGroup.Use()
{
v1NotifyGroup.POST("/:path", v1.PostNotifyMessage)
// merge to system
v1NotifyGroup.POST("/system_status", v1.PostSystemStatusNotify)
}
}
return r
}

View file

@ -3,9 +3,12 @@ package v1
import (
"encoding/json"
"io/ioutil"
"net/http"
"path/filepath"
"strconv"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
@ -14,6 +17,11 @@ import (
"github.com/gin-gonic/gin"
)
const (
dockerRootDirFilePath = "/var/lib/casaos/docker_root"
dockerDaemonConfigurationFilePath = "/etc/docker/daemon.json"
)
// @Summary 获取远程列表
// @Produce application/json
// @Accept application/json
@ -27,8 +35,7 @@ import (
// @Success 200 {string} string "ok"
// @Router /app/list [get]
func AppList(c *gin.Context) {
//service.MyService.Docker().DockerContainerCommit("test2")
// service.MyService.Docker().DockerContainerCommit("test2")
index := c.DefaultQuery("index", "1")
size := c.DefaultQuery("size", "10000")
@ -137,7 +144,7 @@ func MyAppList(c *gin.Context) {
func AppUsageList(c *gin.Context) {
list := service.MyService.App().GetHardwareUsage()
c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
//c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: nil})
// c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: nil})
}
// @Summary 应用详情
@ -149,7 +156,6 @@ func AppUsageList(c *gin.Context) {
// @Success 200 {string} string "ok"
// @Router /app/appinfo/{id} [get]
func AppInfo(c *gin.Context) {
id := c.Param("id")
language := c.GetHeader("Language")
info, err := service.MyService.Casa().GetServerAppInfo(id, "", language)
@ -211,7 +217,7 @@ func AppInfo(c *gin.Context) {
// return c1.Type < c2.Type
// }
//sort
// sort
// if info.NetworkModel != "host" {
// sort.PortsSort(portOrder).Sort(info.Configures.TcpPorts)
// sort.PortsSort(portOrder).Sort(info.Configures.UdpPorts)
@ -262,3 +268,88 @@ func ShareAppFile(c *gin.Context) {
content := service.MyService.Casa().ShareAppFile(str)
c.JSON(common_err.SUCCESS, json.RawMessage(content))
}
func GetDockerDaemonConfiguration(c *gin.Context) {
// info, err := service.MyService.Docker().GetDockerInfo()
// 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
// }
data := make(map[string]interface{})
if file.Exists(dockerRootDirFilePath) {
buf := file.ReadFullFile(dockerRootDirFilePath)
err := json.Unmarshal(buf, &data)
if err != nil {
c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err})
return
}
}
c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
}
func PutDockerDaemonConfiguration(c *gin.Context) {
request := make(map[string]interface{})
if err := c.BindJSON(&request); err != nil {
c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err})
return
}
value, ok := request["docker_root_dir"]
if !ok {
c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: "`docker_root_dir` should not empty"})
return
}
dockerConfig := model.DockerDaemonConfigurationModel{}
if file.Exists(dockerDaemonConfigurationFilePath) {
byteResult := file.ReadFullFile(dockerDaemonConfigurationFilePath)
err := json.Unmarshal(byteResult, &dockerConfig)
if err != nil {
c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to deserialize " + dockerDaemonConfigurationFilePath, Data: err})
return
}
}
dockerRootDir := value.(string)
if dockerRootDir == "/" {
dockerConfig.Root = "" // omitempty - empty string will not be serialized
} else {
if !file.Exists(dockerRootDir) {
c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS), Data: common_err.GetMsg(common_err.DIR_NOT_EXISTS)})
return
}
dockerConfig.Root = filepath.Join(dockerRootDir, "docker")
if err := file.IsNotExistMkDir(dockerConfig.Root); err != nil {
c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to create " + dockerConfig.Root, Data: err})
return
}
}
if buf, err := json.Marshal(request); err != nil {
c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: "error when trying to serialize docker root json", Data: err})
return
} else {
if err := file.WriteToFullPath(buf, dockerRootDirFilePath, 0o644); err != nil {
c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to write " + dockerRootDirFilePath, Data: err})
return
}
}
if buf, err := json.Marshal(dockerConfig); err != nil {
c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: "error when trying to serialize docker config", Data: dockerConfig})
return
} else {
if err := file.WriteToFullPath(buf, dockerDaemonConfigurationFilePath, 0o644); err != nil {
c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to write to " + dockerDaemonConfigurationFilePath, Data: err})
return
}
}
println(command.ExecResultStr("systemctl daemon-reload"))
println(command.ExecResultStr("systemctl restart docker"))
c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: request})
}

View file

@ -1,622 +0,0 @@
package v1
import (
"fmt"
"net/http"
"path/filepath"
"reflect"
"strconv"
"strings"
"time"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/model/notify"
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
"github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS-Common/utils/jwt"
"github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/gin-gonic/gin"
"github.com/shirou/gopsutil/v3/disk"
)
var diskMap = make(map[string]string)
// @Summary disk list
// @Produce application/json
// @Accept application/json
// @Tags disk
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /disk/list [get]
func GetDiskList(c *gin.Context) {
path := c.Query("path")
if len(path) > 0 {
m := service.MyService.Disk().GetDiskInfo(path)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: m})
return
}
t := c.DefaultQuery("type", "")
list := service.MyService.Disk().LSBLK(false)
if t == "usb" {
data := []model.DriveUSB{}
for _, v := range list {
if v.Tran == "usb" {
temp := model.DriveUSB{}
temp.Model = v.Model
temp.Name = v.Name
temp.Size = v.Size
for _, child := range v.Children {
if len(child.MountPoint) > 0 {
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
temp.Avail += avail
}
}
data = append(data, temp)
}
}
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
return
}
dbList := service.MyService.Disk().GetSerialAll()
part := make(map[string]int64, len(dbList))
for _, v := range dbList {
part[v.MountPoint] = v.CreatedAt
}
findSystem := 0
disks := []model.Drive{}
storage := []model.Storage{}
avail := []model.Drive{}
for i := 0; i < len(list); i++ {
disk := model.Drive{}
if list[i].Rota {
disk.DiskType = "HDD"
} else {
disk.DiskType = "SSD"
}
disk.Serial = list[i].Serial
disk.Name = list[i].Name
disk.Size = list[i].Size
disk.Path = list[i].Path
disk.Model = list[i].Model
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.MountPoint = v.MountPoint
stor.Size = v.FSSize
stor.Avail = v.FSAvail
stor.Path = v.Path
stor.Type = v.FsType
stor.DriveName = "System"
disk.Model = "System"
if strings.Contains(v.SubSystems, "mmc") {
disk.DiskType = "MMC"
} else if strings.Contains(v.SubSystems, "usb") {
disk.DiskType = "USB"
}
disk.Health = "true"
disks = append(disks, disk)
storage = append(storage, stor)
findSystem = 1
break
}
}
} else {
if list[i].Children[j].MountPoint == "/" {
stor := model.Storage{}
stor.MountPoint = list[i].Children[j].MountPoint
stor.Size = list[i].Children[j].FSSize
stor.Avail = list[i].Children[j].FSAvail
stor.Path = list[i].Children[j].Path
stor.Type = list[i].Children[j].FsType
stor.DriveName = "System"
disk.Model = "System"
if strings.Contains(list[i].Children[j].SubSystems, "mmc") {
disk.DiskType = "MMC"
} else if strings.Contains(list[i].Children[j].SubSystems, "usb") {
disk.DiskType = "USB"
}
disk.Health = "true"
disks = append(disks, disk)
storage = append(storage, stor)
findSystem = 1
break
}
}
}
}
if findSystem == 1 {
findSystem += 1
continue
}
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") {
temp := service.MyService.Disk().SmartCTL(list[i].Path)
if reflect.DeepEqual(temp, model.SmartctlA{}) {
temp.SmartStatus.Passed = true
}
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)
disks = append(disks, disk)
}
}
data := make(map[string]interface{}, 3)
data["drive"] = disks
data["storage"] = storage
data["avail"] = avail
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
if len(tempChildren.Name) == 0 {
tempChildren.Name = filepath.Base(child.MountPoint)
}
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) {
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
}
token := c.GetHeader("Authorization")
if len(token) == 0 {
token = c.Query("token")
}
claims, err := jwt.ParseToken(token, true)
if err != nil {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
return
}
if encryption.GetMD5ByStr(pwd) != claims.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.Shares().DeleteShareByPath(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
// @Tags disk
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /disk/lists [get]
func GetPlugInDisks(c *gin.Context) {
list := service.MyService.Disk().LSBLK(true)
var result []*disk.UsageStat
for _, item := range list {
result = append(result, service.MyService.Disk().GetDiskInfoByPath(item.Path))
}
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: result})
}
// @Summary disk detail
// @Produce application/json
// @Accept application/json
// @Tags disk
// @Security ApiKeyAuth
// @Param path query string true "for example /dev/sda"
// @Success 200 {string} string "ok"
// @Router /disk/info [get]
func GetDiskInfo(c *gin.Context) {
path := c.Query("path")
if len(path) == 0 {
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
}
m := service.MyService.Disk().GetDiskInfo(path)
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: m})
}
// @Summary 获取支持的格式
// @Produce application/json
// @Accept application/json
// @Tags disk
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /disk/type [get]
func FormatDiskType(c *gin.Context) {
var strArr = [4]string{"fat32", "ntfs", "ext4", "exfat"}
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: strArr})
}
// @Summary 删除分区
// @Produce application/json
// @Accept multipart/form-data
// @Tags disk
// @Security ApiKeyAuth
// @Param path formData string true "磁盘路径 例如/dev/sda1"
// @Success 200 {string} string "ok"
// @Router /disk/delpart [delete]
func RemovePartition(c *gin.Context) {
js := make(map[string]string)
c.ShouldBind(&js)
path := js["path"]
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)})
}
var p = path[:len(path)-1]
var n = path[len(path)-1:]
service.MyService.Disk().DelPartition(p, n)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
}
// @Summary add storage
// @Produce application/json
// @Accept multipart/form-data
// @Tags disk
// @Security ApiKeyAuth
// @Param path formData string true "disk path e.g. /dev/sda"
// @Param serial formData string true "serial"
// @Param name formData string true "name"
// @Param format formData bool true "need format(true)"
// @Success 200 {string} string "ok"
// @Router /disk/storage [post]
func PostDiskAddPartition(c *gin.Context) {
js := make(map[string]interface{})
c.ShouldBind(&js)
path := js["path"].(string)
name := js["name"].(string)
format := js["format"].(bool)
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
}
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)
// 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 {
// format := service.MyService.Disk().FormatDisk(path+"1", "ext4")
// if len(format) == 0 {
// delete(diskMap, path)
// c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FORMAT_ERROR, Message: common_err.GetMsg(common_err.FORMAT_ERROR)})
// return
// }
service.MyService.Disk().AddPartition(path)
}
// 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
// }
fmt.Println(name)
if len(name) == 0 {
name = "Storage"
}
fmt.Println(name)
for i := 0; i < len(currentDisk.Children); i++ {
childrenName := currentDisk.Children[i].Label
if len(childrenName) == 0 {
//childrenName = name + "_" + currentDisk.Children[i].Name
childrenName = name + "_" + strconv.Itoa(i+1)
}
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)
}
service.MyService.Disk().RemoveLSBLKCache()
delete(diskMap, path)
//send notify to client
msg := notify.StorageMessage{}
msg.Action = "ADDED"
msg.Path = currentDisk.Children[0].Path
msg.Volume = "/DATA/"
msg.Size = currentDisk.Children[0].Size
msg.Type = currentDisk.Children[0].Tran
service.MyService.Notify().SendStorageBySocket(msg)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
}
// @Param pwd formData string true "user password"
// @Param volume formData string true "mount point"
// @Success 200 {string} string "ok"
// @Router /disk/format [post]
func PostDiskFormat(c *gin.Context) {
js := make(map[string]string)
c.ShouldBind(&js)
path := js["path"]
t := "ext4"
pwd := js["password"]
volume := js["volume"]
token := c.GetHeader("Authorization")
if len(token) == 0 {
token = c.Query("token")
}
claims, err := jwt.ParseToken(token, true)
if err != nil {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
return
}
if encryption.GetMD5ByStr(pwd) != claims.Password {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
return
}
if len(path) == 0 || len(t) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
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
}
diskMap[path] = "busying"
service.MyService.Disk().UmountPointAndRemoveDir(path)
format := service.MyService.Disk().FormatDisk(path, t)
if len(format) == 0 {
delete(diskMap, path)
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FORMAT_ERROR, Message: common_err.GetMsg(common_err.FORMAT_ERROR)})
return
}
service.MyService.Disk().MountDisk(path, volume)
service.MyService.Disk().RemoveLSBLKCache()
delete(diskMap, path)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
}
// @Summary remove mount point
// @Produce application/json
// @Accept multipart/form-data
// @Tags disk
// @Security ApiKeyAuth
// @Param path formData string true "e.g. /dev/sda1"
// @Param mount_point formData string true "e.g. /mnt/volume1"
// @Param pwd formData string true "user password"
// @Success 200 {string} string "ok"
// @Router /disk/umount [post]
func PostDiskUmount(c *gin.Context) {
js := make(map[string]string)
c.ShouldBind(&js)
path := js["path"]
mountPoint := js["volume"]
pwd := js["password"]
if len(path) == 0 || len(mountPoint) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
token := c.GetHeader("Authorization")
if len(token) == 0 {
token = c.Query("token")
}
claims, err := jwt.ParseToken(token, true)
if err != nil {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
return
}
if encryption.GetMD5ByStr(pwd) != claims.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
}
service.MyService.Disk().UmountPointAndRemoveDir(path)
//delete data
service.MyService.Disk().DeleteMountPoint(path, mountPoint)
service.MyService.Disk().RemoveLSBLKCache()
//send notify to client
msg := notify.StorageMessage{}
msg.Action = "REMOVED"
msg.Path = path
msg.Volume = mountPoint
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)})
}
// @Summary confirm delete disk
// @Produce application/json
// @Accept application/json
// @Tags disk
// @Security ApiKeyAuth
// @Param id path string true "id"
// @Success 200 {string} string "ok"
// @Router /disk/remove/{id} [delete]
func DeleteDisk(c *gin.Context) {
id := c.Param("id")
service.MyService.Disk().DeleteMount(id)
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
}
// @Summary check mount point
// @Produce application/json
// @Accept application/json
// @Tags disk
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /disk/init [get]
func GetDiskCheck(c *gin.Context) {
dbList := service.MyService.Disk().GetSerialAll()
list := service.MyService.Disk().LSBLK(true)
mapList := make(map[string]string)
for _, v := range list {
mapList[v.Serial] = "1"
}
for _, v := range dbList {
if _, ok := mapList[v.UUID]; !ok {
//disk undefind
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: "disk undefind"})
return
}
}
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
}

View file

@ -761,7 +761,7 @@ func ChangAppState(c *gin.Context) {
func ContainerLog(c *gin.Context) {
appId := c.Param("id")
log, _ := service.MyService.Docker().DockerContainerLog(appId)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: log})
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: string(log)})
}
// @Summary 获取容器状态
@ -877,7 +877,7 @@ func UpdateSetting(c *gin.Context) {
if err != nil {
service.MyService.Docker().DockerContainerUpdateName(m.ContainerName, id)
service.MyService.Docker().DockerContainerStart(id)
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
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
}
// echo -e "hellow\nworld" >>

View file

@ -16,12 +16,13 @@ import (
"sync"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin"
uuid "github.com/satori/go.uuid"
"go.uber.org/zap"
)
// @Summary 读取文件
@ -48,7 +49,7 @@ func GetFilerContent(c *gin.Context) {
})
return
}
//文件读取任务是将文件内容读取到内存中。
// 文件读取任务是将文件内容读取到内存中。
info, err := ioutil.ReadFile(filePath)
if err != nil {
c.JSON(common_err.SERVICE_ERROR, model.Result{
@ -84,7 +85,6 @@ func GetLocalFile(c *gin.Context) {
return
}
c.File(path)
return
}
// @Summary download
@ -97,7 +97,6 @@ func GetLocalFile(c *gin.Context) {
// @Success 200 {string} string "ok"
// @Router /file/download [get]
func GetDownloadFile(c *gin.Context) {
t := c.Query("format")
files := c.Query("files")
@ -136,11 +135,11 @@ func GetDownloadFile(c *gin.Context) {
}
if !info.IsDir() {
//打开文件
// 打开文件
fileTmp, _ := os.Open(filePath)
defer fileTmp.Close()
//获取文件的名称
// 获取文件的名称
fileName := path.Base(filePath)
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
c.File(filePath)
@ -180,7 +179,6 @@ func GetDownloadFile(c *gin.Context) {
log.Printf("Failed to archive %s: %v", fname, err)
}
}
}
func GetDownloadSingleFile(c *gin.Context) {
@ -203,7 +201,7 @@ func GetDownloadSingleFile(c *gin.Context) {
defer fileTmp.Close()
fileName := path.Base(filePath)
//c.Header("Content-Disposition", "inline")
// c.Header("Content-Disposition", "inline")
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
c.File(filePath)
}
@ -236,33 +234,8 @@ func DirPath(c *gin.Context) {
info[i].Type = "application"
}
}
} else if path == "/DATA" {
disk := make(map[string]string)
lsblk := service.MyService.Disk().LSBLK(true)
for _, v := range lsblk {
if len(v.Children) > 0 {
t := v.Tran
for _, c := range v.Children {
if len(c.Children) > 0 {
for _, gc := range c.Children {
if len(gc.MountPoint) > 0 {
disk[gc.MountPoint] = t
}
}
}
if len(c.MountPoint) > 0 {
disk[c.MountPoint] = t
}
}
}
}
for i := 0; i < len(info); i++ {
if v, ok := disk[info[i].Path]; ok {
info[i].Type = v
}
}
}
for i := 0; i < len(info); i++ {
if v, ok := sharesMap[info[i].Path]; ok {
ex := make(map[string]interface{})
@ -274,7 +247,7 @@ func DirPath(c *gin.Context) {
info[i].Extensions = ex
}
}
//Hide the files or folders in operation
// Hide the files or folders in operation
fileQueue := make(map[string]string)
if len(service.OpStrArr) > 0 {
for _, v := range service.OpStrArr {
@ -292,6 +265,9 @@ func DirPath(c *gin.Context) {
pathList := []model.Path{}
for i := 0; i < len(info); i++ {
if info[i].Name == ".temp" && info[i].IsDir {
continue
}
if _, ok := fileQueue[info[i].Path]; !ok {
pathList = append(pathList, info[i])
}
@ -384,7 +360,6 @@ func PostCreateFile(c *gin.Context) {
// @Success 200 {string} string "ok"
// @Router /file/upload [get]
func GetFileUpload(c *gin.Context) {
relative := c.Query("relativePath")
fileName := c.Query("filename")
chunkNumber := c.Query("chunkNumber")
@ -392,7 +367,7 @@ func GetFileUpload(c *gin.Context) {
path := c.Query("path")
dirPath := ""
hash := file.GetHashByContent([]byte(fileName))
tempDir := config.AppInfo.TempPath + "/" + hash + strconv.Itoa(totalChunks) + "/"
tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/"
if fileName != relative {
dirPath = strings.TrimSuffix(relative, fileName)
tempDir += dirPath
@ -428,55 +403,91 @@ func PostFileUpload(c *gin.Context) {
hash := file.GetHashByContent([]byte(fileName))
if len(path) == 0 {
c.JSON(common_err.INVALID_PARAMS, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
loger.Error("path should not be empty")
c.JSON(http.StatusBadRequest, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
tempDir := config.AppInfo.TempPath + "/" + hash + strconv.Itoa(totalChunks) + "/"
tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/"
if fileName != relative {
dirPath = strings.TrimSuffix(relative, fileName)
tempDir += dirPath
file.MkDir(path + "/" + dirPath)
if err := file.MkDir(path + "/" + dirPath); err != nil {
loger.Error("error when trying to create `"+path+"/"+dirPath+"`", zap.Error(err))
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
return
}
}
path += "/" + relative
if !file.CheckNotExist(tempDir + chunkNumber) {
file.RMDir(tempDir + chunkNumber)
if err := file.RMDir(tempDir + chunkNumber); err != nil {
loger.Error("error when trying to remove existing `"+tempDir+chunkNumber+"`", zap.Error(err))
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
return
}
}
if totalChunks > 1 {
file.IsNotExistMkDir(tempDir)
out, _ := os.OpenFile(tempDir+chunkNumber, os.O_WRONLY|os.O_CREATE, 0644)
defer out.Close()
_, err := io.Copy(out, f)
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()})
if err := file.IsNotExistMkDir(tempDir); err != nil {
loger.Error("error when trying to create `"+tempDir+"`", zap.Error(err))
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
return
}
out, err := os.OpenFile(tempDir+chunkNumber, os.O_WRONLY|os.O_CREATE, 0o644)
if err != nil {
loger.Error("error when trying to open `"+tempDir+chunkNumber+"` for creation", zap.Error(err))
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
return
}
defer out.Close()
if _, err := io.Copy(out, f); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster copy
loger.Error("error when trying to write to `"+tempDir+chunkNumber+"`", zap.Error(err))
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
return
}
fileNum, err := ioutil.ReadDir(tempDir)
if err != nil {
loger.Error("error when trying to read number of files under `"+tempDir+"`", zap.Error(err))
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
return
}
if totalChunks == len(fileNum) {
if err := file.SpliceFiles(tempDir, path, totalChunks, 1); err != nil {
loger.Error("error when trying to splice files under `"+tempDir+"`", zap.Error(err))
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
return
}
if err := file.RMDir(tempDir); err != nil {
loger.Error("error when trying to remove `"+tempDir+"`", zap.Error(err))
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
return
}
}
} else {
out, _ := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0644)
defer out.Close()
_, err := io.Copy(out, f)
out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0o644)
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()})
loger.Error("error when trying to open `"+path+"` for creation", zap.Error(err))
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
return
}
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
return
}
fileNum, err := ioutil.ReadDir(tempDir)
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
}
if totalChunks == len(fileNum) {
file.SpliceFiles(tempDir, path, totalChunks, 1)
file.RMDir(tempDir)
}
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
defer out.Close()
if _, err := io.Copy(out, f); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster copy
loger.Error("error when trying to write to `"+path+"`", zap.Error(err))
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
return
}
}
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
}
// @Summary copy or move file
@ -488,7 +499,6 @@ func PostFileUpload(c *gin.Context) {
// @Success 200 {string} string "ok"
// @Router /file/operate [post]
func PostOperateFileOrDir(c *gin.Context) {
list := model.FileOperate{}
c.ShouldBind(&list)
@ -538,7 +548,6 @@ func PostOperateFileOrDir(c *gin.Context) {
// @Success 200 {string} string "ok"
// @Router /file/delete [delete]
func DeleteFile(c *gin.Context) {
paths := []string{}
c.ShouldBind(&paths)
if len(paths) == 0 {
@ -570,7 +579,6 @@ func DeleteFile(c *gin.Context) {
// @Success 200 {string} string "ok"
// @Router /file/update [put]
func PutFileContent(c *gin.Context) {
fi := model.FileUpdate{}
c.ShouldBind(&fi)
@ -580,7 +588,7 @@ func PutFileContent(c *gin.Context) {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
return
}
//err := os.Remove(path)
// err := os.Remove(path)
err := os.RemoveAll(fi.FilePath)
if err != nil {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_DELETE_ERROR, Message: common_err.GetMsg(common_err.FILE_DELETE_ERROR), Data: err})

23
route/v1/notiry.go Normal file
View file

@ -0,0 +1,23 @@
package v1
import (
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin"
)
func PostNotifyMessage(c *gin.Context) {
path := c.Param("path")
message := make(map[string]interface{})
c.ShouldBind(&message)
service.MyService.Notify().SendNotify(path, message)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
}
func PostSystemStatusNotify(c *gin.Context) {
message := make(map[string]interface{})
c.ShouldBind(&message)
service.MyService.Notify().SettingSystemTempData(message)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
}

View file

@ -1,109 +0,0 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-07-11 16:02:29
* @LastEditors: LinkLeong
* @LastEditTime: 2022-08-17 19:14:50
* @FilePath: /CasaOS/route/v1/storage.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package v1
import (
"path/filepath"
"reflect"
"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 {
if stor.MountPoint == "/" {
stor.Label = "System"
} else {
stor.Label = filepath.Base(stor.MountPoint)
}
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})
}

View file

@ -7,7 +7,6 @@ import (
"io/ioutil"
"net/http"
"os"
"reflect"
"strconv"
"strings"
"time"
@ -16,14 +15,12 @@ import (
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
"github.com/IceWhaleTech/CasaOS/pkg/utils/version"
"github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/IceWhaleTech/CasaOS/types"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
// @Summary check version
@ -79,7 +76,7 @@ func GetCasaOSErrorLogs(c *gin.Context) {
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: service.MyService.System().GetCasaOSLogs(line)})
}
//系统配置
// 系统配置
func GetSystemConfigDebug(c *gin.Context) {
array := service.MyService.System().GetSystemConfigDebug()
disk := service.MyService.System().GetDiskInfo()
@ -167,101 +164,6 @@ func PostKillCasaOS(c *gin.Context) {
os.Exit(0)
}
// @Summary Turn off usb auto-mount
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/usb/off [put]
func PutSystemUSBAutoMount(c *gin.Context) {
js := make(map[string]string)
c.ShouldBind(&js)
status := js["state"]
if status == "on" {
service.MyService.System().UpdateUSBAutoMount("True")
service.MyService.System().ExecUSBAutoMountShell("True")
} else {
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,
Message: common_err.GetMsg(common_err.SUCCESS),
})
}
// @Summary Turn off usb auto-mount
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/usb [get]
func GetSystemUSBAutoMount(c *gin.Context) {
state := "True"
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,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: state,
})
}
func GetSystemAppsStatus(c *gin.Context) {
systemAppList := service.MyService.App().GetSystemAppList()
appList := []model2.MyAppList{}
@ -278,12 +180,12 @@ func GetSystemAppsStatus(c *gin.Context) {
Id: v.ID,
Port: v.Labels["web"],
Index: v.Labels["index"],
//Order: m.Labels["order"],
// Order: m.Labels["order"],
Image: v.Image,
Latest: false,
//Type: m.Labels["origin"],
//Slogan: m.Slogan,
//Rely: m.Rely,
// Type: m.Labels["origin"],
// Slogan: m.Slogan,
// Rely: m.Rely,
Host: v.Labels["host"],
Protocol: v.Labels["protocol"],
})
@ -304,7 +206,6 @@ func GetSystemAppsStatus(c *gin.Context) {
// @Success 200 {string} string "ok"
// @Router /sys/hardware/info [get]
func GetSystemHardwareInfo(c *gin.Context) {
data := make(map[string]string, 1)
data["drive_model"] = service.MyService.System().GetDeviceTree()
c.JSON(common_err.SUCCESS,
@ -323,99 +224,7 @@ func GetSystemHardwareInfo(c *gin.Context) {
// @Success 200 {string} string "ok"
// @Router /sys/utilization [get]
func GetSystemUtilization(c *gin.Context) {
var data = make(map[string]interface{}, 6)
list := service.MyService.Disk().LSBLK(true)
summary := model.Summary{}
healthy := true
findSystem := 0
for i := 0; i < len(list); i++ {
if len(list[i].Children) > 0 && findSystem == 0 {
for j := 0; j < len(list[i].Children); j++ {
if len(list[i].Children[j].Children) > 0 {
for _, v := range list[i].Children[j].Children {
if v.MountPoint == "/" {
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
loger.Info("disk info", zap.Any("/ total:", s))
loger.Info("disk path", zap.Any("path", v.Path))
summary.Size += s
summary.Avail += a
summary.Used += u
findSystem = 1
break
}
}
} else {
if list[i].Children[j].MountPoint == "/" {
s, _ := strconv.ParseUint(list[i].Children[j].FSSize, 10, 64)
a, _ := strconv.ParseUint(list[i].Children[j].FSAvail, 10, 64)
u, _ := strconv.ParseUint(list[i].Children[j].FSUsed, 10, 64)
loger.Info("disk info", zap.Any("/ total:", s))
loger.Info("disk path", zap.Any("path", list[i].Path))
summary.Size += s
summary.Avail += a
summary.Used += u
findSystem = 1
break
}
}
}
}
if findSystem == 1 {
findSystem += 1
continue
}
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") {
temp := service.MyService.Disk().SmartCTL(list[i].Path)
if reflect.DeepEqual(temp, model.SmartctlA{}) {
healthy = true
} else {
healthy = temp.SmartStatus.Passed
}
if len(list[i].Children) > 0 {
for _, v := range list[i].Children {
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
loger.Info("disk info", zap.Any("/ total:", s))
loger.Info("disk path", zap.Any("path", list[i].Path))
summary.Size += s
summary.Avail += a
summary.Used += u
}
}
}
}
summary.Health = healthy
data["disk"] = summary
usbList := service.MyService.Disk().LSBLK(false)
usb := []model.DriveUSB{}
for _, v := range usbList {
if v.Tran == "usb" {
temp := model.DriveUSB{}
temp.Model = v.Model
temp.Name = v.Name
temp.Size = v.Size
for _, child := range v.Children {
if len(child.MountPoint) > 0 {
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
temp.Avail += avail
}
}
usb = append(usb, temp)
}
}
data["usb"] = usb
data := make(map[string]interface{})
cpu := service.MyService.System().GetCpuPercent()
num := service.MyService.System().GetCpuCoreNum()
cpuData := make(map[string]interface{})
@ -427,7 +236,7 @@ func GetSystemUtilization(c *gin.Context) {
data["cpu"] = cpuData
data["mem"] = service.MyService.System().GetMemInfo()
//拼装网络信息
// 拼装网络信息
netList := service.MyService.System().GetNetInfo()
newNet := []model.IOCountersStat{}
nets := service.MyService.System().GetNet(true)
@ -444,7 +253,9 @@ func GetSystemUtilization(c *gin.Context) {
}
data["net"] = newNet
for k, v := range service.MyService.Notify().GetSystemTempMap() {
data[k] = v
}
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
}
@ -456,7 +267,6 @@ func GetSystemUtilization(c *gin.Context) {
// @Success 200 {string} string "ok"
// @Router /sys/socket/port [get]
func GetSystemSocketPort(c *gin.Context) {
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
@ -479,7 +289,6 @@ func GetSystemCupInfo(c *gin.Context) {
data["percent"] = cpu
data["num"] = num
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
}
// @Summary get mem info
@ -492,7 +301,6 @@ func GetSystemCupInfo(c *gin.Context) {
func GetSystemMemInfo(c *gin.Context) {
mem := service.MyService.System().GetMemInfo()
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: mem})
}
// @Summary get disk info

View file

@ -130,10 +130,6 @@ func (o *casaService) AsyncGetServerList() (collection model.ServerAppListCollec
errr := json2.Unmarshal(results, &collection)
if errr != nil {
loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(results)))
} else {
if collection.Version == o.GetCasaosVersion().Version {
return collection, err
}
}
head := make(map[string]string)
@ -204,10 +200,6 @@ func (o *casaService) AsyncGetServerCategoryList() ([]model.CategoryList, error)
err := json2.Unmarshal(results, &list)
if err != nil {
loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(results)))
} else {
if list.Version == o.GetCasaosVersion().Version {
return list.Item, nil
}
}
item := []model.CategoryList{}
head := make(map[string]string)

View file

@ -1,285 +0,0 @@
package service
import (
json2 "encoding/json"
"fmt"
"reflect"
"strconv"
"strings"
"time"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/shirou/gopsutil/v3/disk"
"github.com/tidwall/gjson"
"go.uber.org/zap"
"gorm.io/gorm"
)
type DiskService interface {
GetPlugInDisk() []string
LSBLK(isUseCache bool) []model.LSBLKModel
SmartCTL(path string) model.SmartctlA
FormatDisk(path, format string) []string
UmountPointAndRemoveDir(path string) []string
GetDiskInfo(path string) model.LSBLKModel
DelPartition(path, num string) string
AddPartition(path string) string
GetDiskInfoByPath(path string) *disk.UsageStat
MountDisk(path, volume string)
GetSerialAll() []model2.SerialDisk
SaveMountPoint(m model2.SerialDisk)
DeleteMountPoint(path, mountPoint string)
DeleteMount(id string)
UpdateMountPoint(m model2.SerialDisk)
RemoveLSBLKCache()
UmountUSB(path string)
}
type diskService struct {
db *gorm.DB
}
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
if result, ok := Cache.Get(key); ok {
res, ok := result.(model.SmartctlA)
if ok {
return res
}
}
var m model.SmartctlA
str := command2.ExecSmartCTLByPath(path)
if str == nil {
loger.Error("failed to exec shell ", zap.Any("err", "smartctl exec error"))
Cache.Add(key, m, time.Minute*10)
return m
}
err := json2.Unmarshal([]byte(str), &m)
if err != nil {
loger.Error("Failed to unmarshal json", zap.Any("err", err))
}
if !reflect.DeepEqual(m, model.SmartctlA{}) {
Cache.Add(key, m, time.Hour*24)
}
return m
}
//通过脚本获取外挂磁盘
func (d *diskService) GetPlugInDisk() []string {
return command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetPlugInDisk")
}
//格式化硬盘
func (d *diskService) FormatDisk(path, format string) []string {
r := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;FormatDisk " + path + " " + format)
return r
}
//移除挂载点,删除目录
func (d *diskService) UmountPointAndRemoveDir(path string) []string {
r := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;UMountPorintAndRemoveDir " + path)
return r
}
//删除分区
func (d *diskService) DelPartition(path, num string) string {
r := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;DelPartition " + path + " " + num)
fmt.Println(r)
return ""
}
//part
func (d *diskService) AddPartition(path string) string {
command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;AddPartition " + path)
return ""
}
func (d *diskService) AddAllPartition(path string) {
}
//获取硬盘详情
func (d *diskService) GetDiskInfoByPath(path string) *disk.UsageStat {
diskInfo, err := disk.Usage(path + "1")
if err != nil {
fmt.Println(err)
}
diskInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.UsedPercent), 64)
diskInfo.InodesUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.InodesUsedPercent), 64)
return diskInfo
}
//get disk details
func (d *diskService) LSBLK(isUseCache bool) []model.LSBLKModel {
key := "system_lsblk"
var n []model.LSBLKModel
if result, ok := Cache.Get(key); ok && isUseCache {
res, ok := result.([]model.LSBLKModel)
if ok {
return res
}
}
str := command2.ExecLSBLK()
if str == nil {
loger.Error("Failed to exec shell", zap.Any("err", "lsblk exec error"))
return nil
}
var m []model.LSBLKModel
err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &m)
if err != nil {
loger.Error("Failed to unmarshal json", zap.Any("err", err))
}
var c []model.LSBLKModel
var fsused uint64
var health = true
for _, i := range m {
if i.Type != "loop" && !i.RO {
fsused = 0
for _, child := range i.Children {
if child.RM {
child.Health = strings.TrimSpace(command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDiskHealthState " + child.Path))
if strings.ToLower(strings.TrimSpace(child.State)) != "ok" {
health = false
}
f, _ := strconv.ParseUint(child.FSUsed, 10, 64)
fsused += f
} else {
health = false
}
c = append(c, child)
}
//i.Format = strings.TrimSpace(command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDiskType " + i.Path))
if health {
i.Health = "OK"
}
i.FSUsed = strconv.FormatUint(fsused, 10)
i.Children = c
if fsused > 0 {
i.UsedPercent, err = strconv.ParseFloat(fmt.Sprintf("%.4f", float64(fsused)/float64(i.Size)), 64)
if err != nil {
loger.Error("Failed to parse float", zap.Any("err", err))
}
}
n = append(n, i)
health = true
c = []model.LSBLKModel{}
fsused = 0
}
}
if len(n) > 0 {
Cache.Add(key, n, time.Second*100)
}
return n
}
func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
str := command2.ExecLSBLKByPath(path)
if str == nil {
loger.Error("Failed to exec shell", zap.Any("err", "lsblk exec error"))
return model.LSBLKModel{}
}
var ml []model.LSBLKModel
err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &ml)
if err != nil {
loger.Error("Failed to unmarshal json", zap.Any("err", err))
return model.LSBLKModel{}
}
m := model.LSBLKModel{}
if len(ml) > 0 {
m = ml[0]
}
return m
// 下面为计算是否可以继续分区的部分,暂时不需要
chiArr := make(map[string]string)
chiList := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetPartitionSectors " + m.Path)
if len(chiList) == 0 {
loger.Error("chiList length error", zap.Any("err", "chiList length error"))
}
for i := 0; i < len(chiList); i++ {
tempArr := strings.Split(chiList[i], ",")
chiArr[tempArr[0]] = chiList[i]
}
var maxSector uint64 = 0
for i := 0; i < len(m.Children); i++ {
tempArr := strings.Split(chiArr[m.Children[i].Path], ",")
m.Children[i].StartSector, _ = strconv.ParseUint(tempArr[1], 10, 64)
m.Children[i].EndSector, _ = strconv.ParseUint(tempArr[2], 10, 64)
if m.Children[i].EndSector > maxSector {
maxSector = m.Children[i].EndSector
}
}
diskEndSector := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDiskSizeAndSectors " + m.Path)
if len(diskEndSector) < 2 {
loger.Error("diskEndSector length error", zap.Any("err", "diskEndSector length error"))
}
diskEndSectorInt, _ := strconv.ParseUint(diskEndSector[len(diskEndSector)-1], 10, 64)
if (diskEndSectorInt-maxSector)*m.MinIO/1024/1024 > 100 {
//添加可以分区情况
p := model.LSBLKModel{}
p.Path = "可以添加"
m.Children = append(m.Children, p)
}
return m
}
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.Println(r)
}
func (d *diskService) SaveMountPoint(m model2.SerialDisk) {
d.db.Where("uuid = ?", m.UUID).Delete(&model2.SerialDisk{})
d.db.Create(&m)
}
func (d *diskService) UpdateMountPoint(m model2.SerialDisk) {
d.db.Model(&model2.SerialDisk{}).Where("uui = ?", m.UUID).Update("mount_point", m.MountPoint)
}
func (d *diskService) DeleteMount(id string) {
d.db.Delete(&model2.SerialDisk{}).Where("id = ?", id)
}
func (d *diskService) DeleteMountPoint(path, mountPoint string) {
d.db.Where("path = ? AND mount_point = ?", path, mountPoint).Delete(&model2.SerialDisk{})
command2.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;do_umount " + path)
}
func (d *diskService) GetSerialAll() []model2.SerialDisk {
var m []model2.SerialDisk
d.db.Find(&m)
return m
}
func NewDiskService(db *gorm.DB) DiskService {
return &diskService{db: db}
}

View file

@ -52,13 +52,14 @@ type DockerService interface {
DockerContainerStop(id string) error
DockerContainerUpdateName(name, id string) (err error)
DockerContainerUpdate(m model.CustomizationPostData, id string) (err error)
DockerContainerLog(name string) (string, error)
DockerContainerLog(name string) ([]byte, error)
DockerContainerCommit(name string)
DockerContainerList() []types.Container
DockerNetworkModelList() []types.NetworkResource
DockerImageInfo(image string) (types.ImageInspect, error)
GetNetWorkNameByNetWorkID(id string) (string, error)
ContainerExecShell(container_id string) string
GetDockerInfo() (types.Info, error)
}
type dockerService struct {
@ -94,7 +95,7 @@ func (ds *dockerService) ContainerExecShell(container_id string) string {
return exec.ID
}
//创建默认网络
// 创建默认网络
func DockerNetwork() {
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
@ -109,7 +110,7 @@ func DockerNetwork() {
cli.NetworkCreate(context.Background(), docker.NETWORKNAME, types.NetworkCreate{})
}
//根据网络id获取网络名
// 根据网络id获取网络名
func (ds *dockerService) GetNetWorkNameByNetWorkID(id string) (string, error) {
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
defer cli.Close()
@ -122,7 +123,7 @@ func (ds *dockerService) GetNetWorkNameByNetWorkID(id string) (string, error) {
return "", err
}
//拉取镜像
// 拉取镜像
func DockerPull() {
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
@ -141,7 +142,7 @@ func DockerPull() {
}
//拉取镜像
// 拉取镜像
func DockerEx() {
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
@ -292,7 +293,7 @@ func DockerLogs() {
//正式内容
//检查镜像是否存在
// 检查镜像是否存在
func (ds *dockerService) IsExistImage(imageName string) bool {
cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil {
@ -311,7 +312,7 @@ func (ds *dockerService) IsExistImage(imageName string) bool {
return false
}
//安装镜像
// 安装镜像
func (ds *dockerService) DockerPullImage(imageName string, icon, name string) error {
cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil {
@ -365,12 +366,12 @@ func (ds *dockerService) DockerContainerCopyCreate(info *types.ContainerJSON) (c
return container.ID, err
}
//param imageName 镜像名称
//param containerDbId 数据库的id
//param port 容器内部主端口
//param mapPort 容器主端口映射到外部的端口
//param tcp 容器其他tcp端口
//param udp 容器其他udp端口
// param imageName 镜像名称
// param containerDbId 数据库的id
// param port 容器内部主端口
// param mapPort 容器主端口映射到外部的端口
// param tcp 容器其他tcp端口
// param udp 容器其他udp端口
func (ds *dockerService) DockerContainerCreate(m model.CustomizationPostData, id string) (containerId string, err error) {
if len(m.NetworkModel) == 0 {
m.NetworkModel = "bridge"
@ -581,7 +582,7 @@ func (ds *dockerService) DockerContainerCreate(m model.CustomizationPostData, id
return containerDb.ID, err
}
//删除容器
// 删除容器
func (ds *dockerService) DockerContainerRemove(name string, update bool) error {
cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil {
@ -605,7 +606,7 @@ func (ds *dockerService) DockerContainerRemove(name string, update bool) error {
return err
}
//删除镜像
// 删除镜像
func (ds *dockerService) DockerImageRemove(name string) error {
cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil {
@ -653,7 +654,7 @@ Loop:
return err
}
//停止镜像
// 停止镜像
func (ds *dockerService) DockerContainerStop(id string) error {
cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil {
@ -664,7 +665,7 @@ func (ds *dockerService) DockerContainerStop(id string) error {
return err
}
//启动容器
// 启动容器
func (ds *dockerService) DockerContainerStart(name string) error {
cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil {
@ -675,24 +676,27 @@ func (ds *dockerService) DockerContainerStart(name string) error {
return err
}
//查看日志
func (ds *dockerService) DockerContainerLog(name string) (string, error) {
// 查看日志
func (ds *dockerService) DockerContainerLog(name string) ([]byte, error) {
cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil {
return "", err
return []byte(""), err
}
defer cli.Close()
body, err := cli.ContainerLogs(context.Background(), name, types.ContainerLogsOptions{ShowStderr: true, ShowStdout: true})
//body, err := cli.ContainerAttach(context.Background(), name, types.ContainerAttachOptions{Logs: true, Stream: false, Stdin: false, Stdout: false, Stderr: false})
body, err := cli.ContainerLogs(context.Background(), name, types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true})
if err != nil {
return "", err
return []byte(""), err
}
defer body.Close()
content, err := ioutil.ReadAll(body)
//content, err := ioutil.ReadAll(body)
if err != nil {
return "", err
return []byte(""), err
}
return string(content), nil
return content, nil
}
func DockerContainerStats1() error {
@ -714,7 +718,7 @@ func DockerContainerStats1() error {
return nil
}
//获取容器状态
// 获取容器状态
func (ds *dockerService) DockerContainerStats(name string) (string, error) {
cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil {
@ -733,7 +737,7 @@ func (ds *dockerService) DockerContainerStats(name string) (string, error) {
return string(sts), nil
}
//备份容器
// 备份容器
func (ds *dockerService) DockerContainerCommit(name string) {
cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil {
@ -778,7 +782,7 @@ func (ds *dockerService) DockerListByImage(image, version string) (*types.Contai
return &containers[0], nil
}
//获取容器详情
// 获取容器详情
func (ds *dockerService) DockerContainerInfo(name string) (*types.ContainerJSON, error) {
cli, err := client2.NewClientWithOpts(client2.FromEnv)
@ -793,13 +797,13 @@ func (ds *dockerService) DockerContainerInfo(name string) (*types.ContainerJSON,
return &d, nil
}
//更新容器
//param shares cpu优先级
//param containerDbId 数据库的id
//param port 容器内部主端口
//param mapPort 容器主端口映射到外部的端口
//param tcp 容器其他tcp端口
//param udp 容器其他udp端口
// 更新容器
// param shares cpu优先级
// param containerDbId 数据库的id
// param port 容器内部主端口
// param mapPort 容器主端口映射到外部的端口
// param tcp 容器其他tcp端口
// param udp 容器其他udp端口
func (ds *dockerService) DockerContainerUpdate(m model.CustomizationPostData, id string) (err error) {
cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil {
@ -834,9 +838,9 @@ func (ds *dockerService) DockerContainerUpdate(m model.CustomizationPostData, id
return
}
//更新容器名称
//param name 容器名称
//param id 老的容器名称
// 更新容器名称
// param name 容器名称
// param id 老的容器名称
func (ds *dockerService) DockerContainerUpdateName(name, id string) (err error) {
cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil {
@ -851,7 +855,7 @@ func (ds *dockerService) DockerContainerUpdateName(name, id string) (err error)
return
}
//获取网络列表
// 获取网络列表
func (ds *dockerService) DockerNetworkModelList() []types.NetworkResource {
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
@ -863,6 +867,17 @@ func NewDockerService() DockerService {
return &dockerService{rootDir: command2.ExecResultStr(`source ./shell/helper.sh ;GetDockerRootDir`)}
}
func (ds *dockerService) GetDockerInfo() (types.Info, error) {
cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil {
return types.Info{}, err
}
defer cli.Close()
return cli.Info(context.Background())
}
// ---------------------------------------test------------------------------------
//func ServiceCreate() {
// cli, err := client2.NewClientWithOpts(client2.FromEnv)

View file

@ -1,25 +0,0 @@
/*
* @Author: LinkLeong link@icewhale.org
* @Date: 2021-12-07 17:14:41
* @LastEditors: LinkLeong
* @LastEditTime: 2022-08-17 18:46:43
* @FilePath: /CasaOS/service/model/o_disk.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package model
//SerialAdvanced Technology Attachment (STAT)
type SerialDisk struct {
Id uint `gorm:"column:id;primary_key" json:"id"`
UUID string `json:"uuid"`
Path string `json:"path"`
State int `json:"state"`
MountPoint string `json:"mount_point"`
CreatedAt int64 `json:"created_at"`
}
func (p *SerialDisk) TableName() string {
return "o_disk"
}

View file

@ -31,16 +31,38 @@ type NotifyServer interface {
SendNetInfoBySocket(netList []model2.IOCountersStat)
SendCPUInfoBySocket(cpu map[string]interface{})
SendMemInfoBySocket(mem map[string]interface{})
SendUSBInfoBySocket(list []model2.DriveUSB)
SendDiskInfoBySocket(disk model2.Summary)
SendFileOperateNotify(nowSend bool)
SendInstallAppBySocket(app notify.Application)
SendAllHardwareStatusBySocket(disk model2.Summary, list []model2.DriveUSB, mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat)
SendAllHardwareStatusBySocket(mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat)
SendStorageBySocket(message notify.StorageMessage)
SendNotify(path string, message map[string]interface{})
SettingSystemTempData(message map[string]interface{})
GetSystemTempMap() map[string]interface{}
}
type notifyServer struct {
db *gorm.DB
db *gorm.DB
SystemTempMap map[string]interface{}
}
func (i *notifyServer) SettingSystemTempData(message map[string]interface{}) {
for k, v := range message {
i.SystemTempMap[k] = v
}
}
func (i *notifyServer) SendNotify(path string, message map[string]interface{}) {
msg := gosf.Message{}
msg.Body = message
msg.Success = true
msg.Text = path
notify := notify.Message{}
notify.Path = path
notify.Msg = msg
NotifyMsg <- notify
}
func (i *notifyServer) SendStorageBySocket(message notify.StorageMessage) {
@ -58,12 +80,9 @@ func (i *notifyServer) SendStorageBySocket(message notify.StorageMessage) {
NotifyMsg <- notify
}
func (i *notifyServer) SendAllHardwareStatusBySocket(disk model2.Summary, list []model2.DriveUSB, mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) {
func (i *notifyServer) SendAllHardwareStatusBySocket(mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) {
body := make(map[string]interface{})
body["sys_disk"] = disk
body["sys_usb"] = list
body["sys_mem"] = mem
@ -71,6 +90,10 @@ func (i *notifyServer) SendAllHardwareStatusBySocket(disk model2.Summary, list [
body["sys_net"] = netList
for k, v := range i.SystemTempMap {
body[k] = v
}
msg := gosf.Message{}
msg.Body = body
msg.Success = true
@ -239,38 +262,6 @@ func (i *notifyServer) SendFileOperateNotify(nowSend bool) {
}
func (i *notifyServer) SendDiskInfoBySocket(disk model2.Summary) {
body := make(map[string]interface{})
body["data"] = disk
msg := gosf.Message{}
msg.Body = body
msg.Success = true
msg.Text = "sys_disk"
notify := notify.Message{}
notify.Path = "sys_disk"
notify.Msg = msg
NotifyMsg <- notify
}
func (i *notifyServer) SendUSBInfoBySocket(list []model2.DriveUSB) {
body := make(map[string]interface{})
body["data"] = list
msg := gosf.Message{}
msg.Body = body
msg.Success = true
msg.Text = "sys_usb"
notify := notify.Message{}
notify.Path = "sys_usb"
notify.Msg = msg
NotifyMsg <- notify
}
func (i *notifyServer) SendMemInfoBySocket(mem map[string]interface{}) {
body := make(map[string]interface{})
body["data"] = mem
@ -452,7 +443,11 @@ func SendMeg() {
// }
// }
func (i *notifyServer) GetSystemTempMap() map[string]interface{} {
return i.SystemTempMap
func NewNotifyService(db *gorm.DB) NotifyServer {
return &notifyServer{db: db}
}
func NewNotifyService(db *gorm.DB) NotifyServer {
return &notifyServer{db: db, SystemTempMap: make(map[string]interface{})}
}

View file

@ -30,7 +30,6 @@ type Repository interface {
//User() UserService
Docker() DockerService
Casa() CasaService
Disk() DiskService
Notify() NotifyServer
Rely() RelyService
System() SystemService
@ -51,7 +50,6 @@ func NewService(db *gorm.DB, RuntimePath string) Repository {
app: NewAppService(db),
docker: NewDockerService(),
casa: NewCasaService(),
disk: NewDiskService(db),
notify: NewNotifyService(db),
rely: NewRelyService(db),
system: NewSystemService(),
@ -65,7 +63,6 @@ type store struct {
app AppService
docker DockerService
casa CasaService
disk DiskService
notify NotifyServer
rely RelyService
system SystemService
@ -107,7 +104,3 @@ func (c *store) Docker() DockerService {
func (c *store) Casa() CasaService {
return c.casa
}
func (c *store) Disk() DiskService {
return c.disk
}

View file

@ -30,8 +30,6 @@ type SystemService interface {
UpdateAssist()
UpSystemPort(port string)
GetTimeZone() string
UpdateUSBAutoMount(state string)
ExecUSBAutoMountShell(state string)
UpAppOrderFile(str, id string)
GetAppOrderFile(id string) []byte
GetNet(physics bool) []string
@ -53,14 +51,7 @@ type SystemService interface {
GetCPUTemperature() int
GetCPUPower() map[string]string
}
type systemService struct {
}
func (s *systemService) UpdateUSBAutoMount(state string) {
config.ServerInfo.USBAutoMount = state
config.Cfg.Section("server").Key("USBAutoMount").SetValue(state)
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
}
type systemService struct{}
func (c *systemService) MkdirAll(path string) (int, error) {
_, err := os.Stat(path)
@ -76,8 +67,8 @@ func (c *systemService) MkdirAll(path string) (int, error) {
}
return common_err.SERVICE_ERROR, err
}
func (c *systemService) RenameFile(oldF, newF string) (int, error) {
func (c *systemService) RenameFile(oldF, newF string) (int, error) {
_, err := os.Stat(newF)
if err == nil {
return common_err.DIR_ALREADY_EXISTS, nil
@ -92,6 +83,7 @@ func (c *systemService) RenameFile(oldF, newF string) (int, error) {
}
return common_err.SERVICE_ERROR, err
}
func (c *systemService) CreateFile(path string) (int, error) {
_, err := os.Stat(path)
if err == nil {
@ -104,9 +96,11 @@ func (c *systemService) CreateFile(path string) (int, error) {
}
return common_err.SERVICE_ERROR, err
}
func (c *systemService) GetDeviceTree() string {
return command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDeviceTree")
}
func (c *systemService) GetSysInfo() host.InfoStat {
info, _ := host.Info()
return *info
@ -128,9 +122,7 @@ func (c *systemService) GetNetState(name string) string {
}
func (c *systemService) GetDirPathOne(path string) (m model.Path) {
f, err := os.Stat(path)
if err != nil {
return
}
@ -175,6 +167,7 @@ func (c *systemService) GetDirPath(path string) []model.Path {
}
return dirs
}
func (c *systemService) GetCpuInfo() []cpu.InfoStat {
info, _ := cpu.Info()
return info
@ -207,6 +200,7 @@ func (c *systemService) GetNetInfo() []net.IOCountersStat {
parts, _ := net.IOCounters(true)
return parts
}
func (c *systemService) GetNet(physics bool) []string {
t := "1"
if physics {
@ -221,10 +215,16 @@ func (s *systemService) UpdateSystemVersion(version string) {
}
file.CreateFile(config.AppInfo.LogPath + "/upgrade.log")
//go command2.OnlyExec("curl -fsSL https://raw.githubusercontent.com/LinkLeong/casaos-alpha/main/update.sh | bash")
go command2.OnlyExec("curl -fsSL https://raw.githubusercontent.com/IceWhaleTech/get/main/update.sh | bash")
if len(config.ServerInfo.UpdateUrl) > 0 {
go command2.OnlyExec("curl -fsSL " + config.ServerInfo.UpdateUrl + " | bash")
} else {
go command2.OnlyExec("curl -fsSL https://raw.githubusercontent.com/IceWhaleTech/get/main/update.sh | bash")
}
//s.log.Error(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() {
command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/assist.sh")
}
@ -233,14 +233,6 @@ func (s *systemService) GetTimeZone() string {
return command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;GetTimeZone")
}
func (s *systemService) ExecUSBAutoMountShell(state string) {
if state == "False" {
command2.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;USB_Stop_Auto")
} else {
command2.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;USB_Start_Auto")
}
}
func (s *systemService) GetSystemConfigDebug() []string {
return command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetSysInfo")
}
@ -248,9 +240,11 @@ func (s *systemService) GetSystemConfigDebug() []string {
func (s *systemService) UpAppOrderFile(str, id string) {
file.WriteToPath([]byte(str), config.AppInfo.DBPath+"/"+id, "app_order.json")
}
func (s *systemService) GetAppOrderFile(id string) []byte {
return file.ReadFullFile(config.AppInfo.UserDataPath + "/" + id + "/app_order.json")
}
func (s *systemService) UpSystemPort(port string) {
if len(port) > 0 && port != config.ServerInfo.HttpPort {
config.Cfg.Section("server").Key("HttpPort").SetValue(port)
@ -258,6 +252,7 @@ func (s *systemService) UpSystemPort(port string) {
}
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
}
func (s *systemService) GetCasaOSLogs(lineNumber int) string {
file, err := os.Open(filepath.Join(config.AppInfo.LogPath, fmt.Sprintf("%s.%s",
config.AppInfo.LogSaveName,
@ -294,8 +289,8 @@ func GetDeviceAllIP() []string {
func (s *systemService) IsServiceRunning(name string) bool {
status := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;CheckServiceStatus smbd")
return strings.TrimSpace(status) == "running"
}
func (s *systemService) GetCPUTemperature() int {
outPut := ""
if file.Exists("/sys/class/thermal/thermal_zone0/temp") {
@ -313,6 +308,7 @@ func (s *systemService) GetCPUTemperature() int {
}
return celsius
}
func (s *systemService) GetCPUPower() map[string]string {
data := make(map[string]string, 2)
data["timestamp"] = strconv.FormatInt(time.Now().Unix(), 10)
@ -323,6 +319,7 @@ func (s *systemService) GetCPUPower() map[string]string {
}
return data
}
func NewSystemService() SystemService {
return &systemService{}
}

View file

@ -1,15 +1,14 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-02-17 18:53:22
* @LastEditors: LinkLeong
* @LastEditTime: 2022-09-06 14:27:42
* @FilePath: /CasaOS/types/system.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
/*@Author: LinkLeong link@icewhale.com
*@Date: 2022-02-17 18:53:22
*@LastEditors: LinkLeong
*@LastEditTime: 2022-09-06 14:27:42
*@FilePath: /CasaOS/types/system.go
*@Description:
*@Website: https://www.casaos.io
*Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package types
const CURRENTVERSION = "0.3.6"
const CURRENTVERSION = "0.3.7"
const BODY = " "