mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/yunionio/cloudpods.git
synced 2026-09-20 08:03:53 +08:00
Compare commits
159 Commits
v3.11.12-r
...
v3.11.13
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c6d5c9ea0a | ||
|
|
ecb65c2563 | ||
|
|
7dc2246c10 | ||
|
|
0b02c49c7c | ||
|
|
5e565cf2be | ||
|
|
aef2e3e956 | ||
|
|
335cdf37b4 | ||
|
|
43bb829edc | ||
|
|
217496161a | ||
|
|
f2d2495be3 | ||
|
|
b333d023f9 | ||
|
|
29d1a9beb3 | ||
|
|
8a70ad1fe1 | ||
|
|
55c139f4ab | ||
|
|
24fdc3782f | ||
|
|
69fce36cab | ||
|
|
aef3f68fd5 | ||
|
|
67566abfbb | ||
|
|
382ec17c04 | ||
|
|
28f83d8dac | ||
|
|
bdd024d699 | ||
|
|
8f03c28919 | ||
|
|
246721c529 | ||
|
|
60ae50c608 | ||
|
|
60082c3534 | ||
|
|
4a512da8a8 | ||
|
|
4a6adeea1f | ||
|
|
65cbea196f | ||
|
|
45e6c8cf59 | ||
|
|
a36039ccc1 | ||
|
|
a4b5078997 | ||
|
|
4ba88e37cd | ||
|
|
411a6df9f9 | ||
|
|
2ba0bdfee7 | ||
|
|
dffd2aa2d9 | ||
|
|
fec5f1f8a7 | ||
|
|
23e3234d8d | ||
|
|
f6928c9ca9 | ||
|
|
e479741459 | ||
|
|
5560cc9371 | ||
|
|
91061f28cc | ||
|
|
f359c67632 | ||
|
|
7355547b2b | ||
|
|
bcf544574f | ||
|
|
9a01e1fdb3 | ||
|
|
7d92eb9a63 | ||
|
|
6bf92e0ea7 | ||
|
|
5eae491d47 | ||
|
|
532f4eb1db | ||
|
|
26fd3424f3 | ||
|
|
395bc3f317 | ||
|
|
865a019ba3 | ||
|
|
16ce2a6a66 | ||
|
|
7c69f96725 | ||
|
|
231711d0fb | ||
|
|
7c3929bc5e | ||
|
|
c6f3e714ee | ||
|
|
73076cfc19 | ||
|
|
4455a99645 | ||
|
|
c6502eebd7 | ||
|
|
3b7615b264 | ||
|
|
7132a3be67 | ||
|
|
06482d2f20 | ||
|
|
557715bea3 | ||
|
|
0d2cb66dc1 | ||
|
|
166b4b34f5 | ||
|
|
27f44e909a | ||
|
|
52962980c5 | ||
|
|
01cd87d8eb | ||
|
|
323b64116a | ||
|
|
4a3a9f1b11 | ||
|
|
f22db65285 | ||
|
|
9024e78dfc | ||
|
|
92be2b6d11 | ||
|
|
859384643f | ||
|
|
d8ea9f576a | ||
|
|
56711f01f2 | ||
|
|
d9660431fd | ||
|
|
2e58bba807 | ||
|
|
19c0680c4b | ||
|
|
d2c6e5514f | ||
|
|
e175225af5 | ||
|
|
3fccc13548 | ||
|
|
4b78268ff6 | ||
|
|
ae45d0d1d1 | ||
|
|
8e9f4c12c2 | ||
|
|
6e9b1e790f | ||
|
|
2fc05e9bbb | ||
|
|
ef046d10c9 | ||
|
|
350028425e | ||
|
|
49b7f9df7e | ||
|
|
11ec38b8b7 | ||
|
|
0de6db47a8 | ||
|
|
9e72da7b1e | ||
|
|
1875cf7bd6 | ||
|
|
c1e814ba6e | ||
|
|
ea87fbb8aa | ||
|
|
453d47c99b | ||
|
|
3ae144e233 | ||
|
|
873a5d6b16 | ||
|
|
1b212051a9 | ||
|
|
a34da1092c | ||
|
|
aa394ead62 | ||
|
|
039a69eed6 | ||
|
|
8ddca94bdc | ||
|
|
beb3e9f9fd | ||
|
|
bdc3693c2b | ||
|
|
260b8557d8 | ||
|
|
e0706a1b43 | ||
|
|
0ba9578ec7 | ||
|
|
1a1feba74d | ||
|
|
5427facb6a | ||
|
|
6b347bf00c | ||
|
|
357a0f22e3 | ||
|
|
b4fd2eb122 | ||
|
|
a846649f1c | ||
|
|
a10ea01c84 | ||
|
|
2bb2742bf0 | ||
|
|
cd68e4c156 | ||
|
|
78fa396097 | ||
|
|
b4876fa013 | ||
|
|
ea51d3f05f | ||
|
|
d74b732b86 | ||
|
|
7d36c1fe1b | ||
|
|
606916760b | ||
|
|
106f7b3d2a | ||
|
|
807454ab63 | ||
|
|
d5711d7d64 | ||
|
|
b999ad72ac | ||
|
|
fedf62f75b | ||
|
|
451d289903 | ||
|
|
93101837f7 | ||
|
|
a7bc8c0fff | ||
|
|
d913be0312 | ||
|
|
c8efe3d1e6 | ||
|
|
d7b0a10ad9 | ||
|
|
73049f487a | ||
|
|
d9060328fc | ||
|
|
ccf1694237 | ||
|
|
2cb0437596 | ||
|
|
c88e8fef1b | ||
|
|
2ca2435595 | ||
|
|
30bac52d1c | ||
|
|
74a8b5667f | ||
|
|
ec3b52930e | ||
|
|
4703a7094d | ||
|
|
f8a46a06fc | ||
|
|
a64749ef31 | ||
|
|
defb33a861 | ||
|
|
ab6f22c5db | ||
|
|
7947bd6686 | ||
|
|
50ab8bf4d4 | ||
|
|
5a5dbed43b | ||
|
|
96b330b6c4 | ||
|
|
d62f1c1149 | ||
|
|
2b90c029ee | ||
|
|
edefdd6ca1 | ||
|
|
b6c3aa0a7a | ||
|
|
85bc3abc77 |
4
Makefile
4
Makefile
@@ -253,7 +253,7 @@ hostdeployer-grpc-gen:
|
||||
|
||||
check: fmt-check
|
||||
check: gendocgo-check
|
||||
check: goimports-check
|
||||
#check: goimports-check
|
||||
#check: vet-check
|
||||
#check: y18n-check
|
||||
.PHONY: check
|
||||
@@ -277,7 +277,7 @@ dep:
|
||||
@echo "$$depDeprecated"
|
||||
@$(MAKE) mod
|
||||
|
||||
RELEASE_BRANCH:=release/3.11
|
||||
RELEASE_BRANCH:=release/3.11.13
|
||||
GOPROXY ?= direct
|
||||
|
||||
mod:
|
||||
|
||||
@@ -36,6 +36,12 @@ fi
|
||||
. $ROOT/vars
|
||||
|
||||
BUILDROOT=$(mktemp -d 2>/dev/null || mktemp -d -t 'yunion')
|
||||
function cleanup {
|
||||
rm -rf "$BUILDROOT"
|
||||
echo "Deleted temp working directory $BUILDROOT"
|
||||
}
|
||||
# register the cleanup function to be called on the EXIT signal
|
||||
trap cleanup EXIT
|
||||
|
||||
echo "Build root ${BUILDROOT}"
|
||||
|
||||
@@ -104,41 +110,84 @@ if [ -d $ROOT/root ]; then
|
||||
rsync -a $ROOT/root/ \$RPM_BUILD_ROOT
|
||||
fi
|
||||
|
||||
%pre
|
||||
%pre" > $SPEC_FILE
|
||||
|
||||
if [ -f $ROOT/preinst ]; then
|
||||
cat $ROOT/preinst >> $SPEC_FILE
|
||||
else
|
||||
echo "
|
||||
%if %{use_systemd}
|
||||
getent group %{owner} >/dev/null || /usr/sbin/groupadd -r %{owner}
|
||||
getent passwd %{owner} >/dev/null || /usr/sbin/useradd -r -s /sbin/nologin -d %{homedir} -M -g %{owner} %{owner}
|
||||
%endif
|
||||
" >> $SPEC_FILE
|
||||
fi
|
||||
|
||||
%post
|
||||
echo "
|
||||
%post" >> $SPEC_FILE
|
||||
|
||||
if [ -f $ROOT/postinst ]; then
|
||||
cat $ROOT/postinst >> $SPEC_FILE
|
||||
else
|
||||
echo "
|
||||
%if %{use_systemd}
|
||||
mkdir -p /var/run/%{owner}
|
||||
chown -R %{owner}:%{owner} /var/run/%{owner}
|
||||
/usr/bin/systemctl preset %{pkgname}.service >/dev/null 2>&1 ||:
|
||||
%endif
|
||||
" >> $SPEC_FILE
|
||||
fi
|
||||
|
||||
%preun
|
||||
echo "
|
||||
%preun" >> $SPEC_FILE
|
||||
|
||||
if [ -f $ROOT/prerm ]; then
|
||||
cat $ROOT/prerm >> $SPEC_FILE
|
||||
else
|
||||
echo "
|
||||
%if %{use_systemd}
|
||||
/usr/bin/systemctl --no-reload disable %{pkgname}.service >/dev/null 2>&1 || :
|
||||
/usr/bin/systemctl stop %{pkgname}.service >/dev/null 2>&1 ||:
|
||||
%endif
|
||||
" >> $SPEC_FILE
|
||||
fi
|
||||
|
||||
%postun
|
||||
echo "
|
||||
%postun" >> $SPEC_FILE
|
||||
|
||||
if [ -f $ROOT/postrm ]; then
|
||||
cat $ROOT/postrm >> $SPEC_FILE
|
||||
else
|
||||
echo "
|
||||
%if %{use_systemd}
|
||||
/usr/bin/systemctl daemon-reload >/dev/null 2>&1 ||:
|
||||
%endif
|
||||
" >> $SPEC_FILE
|
||||
fi
|
||||
|
||||
echo -n "
|
||||
%files
|
||||
%doc
|
||||
$BIN_PATH/$PKG
|
||||
$(for b in $EXTRA_BINS; do echo $BIN_PATH/$b; done)
|
||||
" > $SPEC_FILE
|
||||
" >> $SPEC_FILE
|
||||
|
||||
for b in $EXTRA_BINS; do
|
||||
echo $BIN_PATH/$b >> $SPEC_FILE
|
||||
done
|
||||
|
||||
if [ -d $ROOT/root/ ]; then
|
||||
find $ROOT/root/ -type f | sed -e "s:$ROOT/root::g" >> $SPEC_FILE
|
||||
fi
|
||||
|
||||
rpmbuild --define "_topdir $BUILDROOT" -bb $SPEC_FILE
|
||||
TARGET=
|
||||
case "$GOARCH" in
|
||||
"arm64" | "aarch64" | "arm")
|
||||
TARGET="--target aarch64-redhat-linux"
|
||||
;;
|
||||
"amd64" | "x86" | "i686" | "i386" | "x86_64")
|
||||
TARGET="--target x86_64-redhat-linux"
|
||||
;;
|
||||
esac
|
||||
|
||||
rpmbuild --define "_topdir $BUILDROOT" -bb $SPEC_FILE $TARGET
|
||||
|
||||
find $RPM_DIR -type f | while read f; do
|
||||
d="$(dirname "$f")"
|
||||
@@ -146,5 +195,3 @@ find $RPM_DIR -type f | while read f; do
|
||||
mkdir -p "$d"
|
||||
cp $f $d
|
||||
done
|
||||
|
||||
rm -fr $BUILDROOT
|
||||
|
||||
@@ -35,26 +35,6 @@ fi
|
||||
|
||||
. $ROOT/vars
|
||||
|
||||
if [ -z "$VERSION" ]; then
|
||||
TAG=$(git describe --abbrev=0 --tags || echo 000000)
|
||||
VERSION=${TAG/\//-}
|
||||
VERSION=${VERSION/v/}
|
||||
fi
|
||||
RELEASE=`date +"%y%m%d%H"`
|
||||
FULL_VERSION=$VERSION-$RELEASE
|
||||
BUILDROOT=$OUTPUT_DIR/yunion-$1-$FULL_VERSION
|
||||
rm -rf $BUILDROOT
|
||||
mkdir -p $BUILDROOT/DEBIAN
|
||||
mkdir -p $BUILDROOT/$BIN_PATH
|
||||
|
||||
cp -rf $BIN $BUILDROOT/$BIN_PATH
|
||||
if [ -d $ROOT/root ]; then
|
||||
cp -rf $ROOT/root/* $BUILDROOT/
|
||||
fi
|
||||
|
||||
|
||||
echo "Build root ${BUILDROOT}"
|
||||
|
||||
case $(uname -m) in
|
||||
x86_64)
|
||||
CURRENT_ARCH=amd64
|
||||
@@ -64,15 +44,123 @@ case $(uname -m) in
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "Package: yunion-$1
|
||||
if [[ -n "$GOARCH" ]]; then
|
||||
case "$GOARCH" in
|
||||
"arm64" | "arm" | "aarch64")
|
||||
CURRENT_ARCH="arm64"
|
||||
;;
|
||||
"x86" | "x86_64" | "i686" | "i386" | "amd64")
|
||||
CURRENT_ARCH="amd64"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ -z "$VERSION" ]; then
|
||||
TAG=$(git describe --abbrev=0 --tags || echo 000000)
|
||||
VERSION=${TAG/\//-}
|
||||
VERSION=${VERSION/v/}
|
||||
VERSION=${VERSION/master-/}
|
||||
fi
|
||||
RELEASE=`date +"%y%m%d%H"`
|
||||
FULL_VERSION=$VERSION-$RELEASE
|
||||
BUILDROOT=$OUTPUT_DIR/yunion-${PKG}-${FULL_VERSION}_${CURRENT_ARCH}
|
||||
function cleanup {
|
||||
rm -rf "$BUILDROOT"
|
||||
echo "Deleted temp working directory $BUILDROOT"
|
||||
}
|
||||
# register the cleanup function to be called on the EXIT signal
|
||||
trap cleanup EXIT
|
||||
|
||||
rm -rf $BUILDROOT
|
||||
mkdir -p $BUILDROOT/DEBIAN
|
||||
mkdir -p $BUILDROOT/$BIN_PATH
|
||||
|
||||
cp -rf $BIN $BUILDROOT/$BIN_PATH
|
||||
if [ -d $ROOT/root ]; then
|
||||
cp -rf $ROOT/root/* $BUILDROOT/
|
||||
fi
|
||||
|
||||
echo "Build root ${BUILDROOT}"
|
||||
|
||||
echo "Package: yunion-$PKG
|
||||
Version: $FULL_VERSION
|
||||
Section: base
|
||||
Priority: optional
|
||||
Architecture: $CURRENT_ARCH
|
||||
Maintainer: wanyaoqi@yunionyun.com
|
||||
Description: Yunion $1
|
||||
" > $BUILDROOT/DEBIAN/control
|
||||
Description: $DESCRIPTION" > $BUILDROOT/DEBIAN/control
|
||||
if [ ${#REQUIRES[@]} -gt 0 ]; then
|
||||
DEPS=$(IFS=, ; echo "${REQUIRES[*]}")
|
||||
echo "Depends: $DEPS" >> $BUILDROOT/DEBIAN/control
|
||||
fi
|
||||
chmod 0755 $BUILDROOT/DEBIAN/control
|
||||
|
||||
cat $BUILDROOT/DEBIAN/control
|
||||
|
||||
dpkg-deb --build $BUILDROOT
|
||||
echo "#!/bin/bash
|
||||
" > $BUILDROOT/DEBIAN/preinst
|
||||
if [ -f $ROOT/preinst ]; then
|
||||
cat $ROOT/preinst >> $BUILDROOT/DEBIAN/preinst
|
||||
else
|
||||
if [ "$SERVICE" == "yes" ] && [ -n "$OWNER" ]; then
|
||||
echo "
|
||||
getent group ${OWNER} >/dev/null || /usr/sbin/groupadd -r ${OWNER}
|
||||
getent passwd ${OWNER} >/dev/null || /usr/sbin/useradd -r -s /sbin/nologin -d /home/${OWNER} -M -g ${OWNER} ${OWNER}
|
||||
" >> $BUILDROOT/DEBIAN/preinst
|
||||
fi
|
||||
fi
|
||||
chmod 0755 $BUILDROOT/DEBIAN/preinst
|
||||
|
||||
echo "#!/bin/bash
|
||||
" > $BUILDROOT/DEBIAN/postinst
|
||||
if [ -f $ROOT/postinst ]; then
|
||||
cat $ROOT/postinst >> $BUILDROOT/DEBIAN/postinst
|
||||
else
|
||||
if [ "$SERVICE" == "yes" ]; then
|
||||
echo "
|
||||
/usr/bin/systemctl preset yunion-${PKG}.service >/dev/null 2>&1 ||:
|
||||
" >> $BUILDROOT/DEBIAN/postinst
|
||||
fi
|
||||
fi
|
||||
chmod 0755 $BUILDROOT/DEBIAN/postinst
|
||||
|
||||
echo "#!/bin/bash
|
||||
" > $BUILDROOT/DEBIAN/prerm
|
||||
if [ -f $ROOT/prerm ]; then
|
||||
cat $ROOT/prerm >> $BUILDROOT/DEBIAN/prerm
|
||||
else
|
||||
if [ "$SERVICE" == "yes" ]; then
|
||||
echo "
|
||||
/usr/bin/systemctl --no-reload disable yunion-${PKG}.service >/dev/null 2>&1 || :
|
||||
/usr/bin/systemctl stop yunion-${PKG}.service >/dev/null 2>&1 ||:
|
||||
" >> $BUILDROOT/DEBIAN/prerm
|
||||
fi
|
||||
fi
|
||||
chmod 0755 $BUILDROOT/DEBIAN/prerm
|
||||
|
||||
echo "#!/bin/bash
|
||||
" > $BUILDROOT/DEBIAN/postrm
|
||||
if [ -f $ROOT/postrm ]; then
|
||||
cat $ROOT/postrm >> $BUILDROOT/DEBIAN/postrm
|
||||
else
|
||||
if [ "$SERVICE" == "yes" ]; then
|
||||
echo "
|
||||
/usr/bin/systemctl daemon-reload >/dev/null 2>&1 ||:
|
||||
" >> $BUILDROOT/DEBIAN/postrm
|
||||
fi
|
||||
fi
|
||||
chmod 0755 $BUILDROOT/DEBIAN/postrm
|
||||
|
||||
dpkg-deb --build $BUILDROOT
|
||||
|
||||
case "$CURRENT_ARCH" in
|
||||
"amd64")
|
||||
DSTARCH="x86_64"
|
||||
;;
|
||||
"arm64")
|
||||
DSTARCH="aarch64"
|
||||
;;
|
||||
esac
|
||||
|
||||
mkdir -p ${OUTPUT_DIR}/${DSTARCH}
|
||||
mv ${BUILDROOT}.deb ${OUTPUT_DIR}/${DSTARCH}/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM registry.cn-beijing.aliyuncs.com/yunionio/baremetal-base:v0.3.9-20231219.0
|
||||
FROM registry.cn-beijing.aliyuncs.com/yunionio/baremetal-base:v0.3.9-20251215.0
|
||||
|
||||
MAINTAINER "Zexi Li <lizexi@yunionyun.com>"
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#FROM --platform=linux/amd64 registry.cn-beijing.aliyuncs.com/yunionio/centos-build:1.1-4 as build
|
||||
#RUN yum install -y https://iso.yunion.cn/vm-images/baremetal-pxerom-1.1.0-21092209.x86_64.rpm
|
||||
#RUN yum install -y http://192.168.23.50:8083/baremetal-pxerom-1.1.0-21092209.x86_64.rpm
|
||||
FROM registry.cn-beijing.aliyuncs.com/yunionio/yunionos:v3.10.8-20231215.0 as yunionos
|
||||
FROM registry.cn-beijing.aliyuncs.com/yunionio/yunionos:v4.0.0-20251201.0 as yunionos
|
||||
|
||||
FROM centos:8 as grub-stage
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM registry.cn-beijing.aliyuncs.com/yunionio/host-deployer-base:1.4.9
|
||||
FROM registry.cn-beijing.aliyuncs.com/yunionio/host-deployer-base:1.4.11
|
||||
|
||||
MAINTAINER "Yaoqi Wan wanyaoqi@yunionyun.com"
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ WEBCONSOLE_BASE_VERSION = 20230731.2
|
||||
webconsole-base:
|
||||
$(DOCKER_BUILDX)/webconsole-base:$(WEBCONSOLE_BASE_VERSION) -f ./Dockerfile.webconsole-base .
|
||||
|
||||
BAREMETAL_BASE_VERSION = v0.3.9-20231219.1
|
||||
BAREMETAL_BASE_VERSION = v0.3.9-20251112.1
|
||||
|
||||
baremetal-base:
|
||||
$(DOCKER_BUILDX)/baremetal-base:$(BAREMETAL_BASE_VERSION) -f ./Dockerfile.baremetal-base .
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
DESCRIPTION="Yunion Cloud Image Service"
|
||||
|
||||
REQUIRES=(
|
||||
yunion-qemu-2.12.1
|
||||
yunion-qemu-4.2.0
|
||||
)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
{{.title}}
|
||||
策略名称: {{.name}}
|
||||
触发时间: {{.start_time}}
|
||||
报警级别: {{.level}}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
{{.title}}
|
||||
AlertName: {{.name}}
|
||||
Time: {{.start_time}}
|
||||
Level: {{.level}}
|
||||
|
||||
@@ -1 +1 @@
|
||||
{{.title}}
|
||||
{{monitorTitle .}}
|
||||
@@ -1 +1 @@
|
||||
{{.title}}
|
||||
{{monitorTitle .}}
|
||||
@@ -1 +1 @@
|
||||
{{.title}}
|
||||
{{monitorTitle .}}
|
||||
@@ -1 +1 @@
|
||||
{{.title}}
|
||||
{{monitorTitle .}}
|
||||
@@ -42,30 +42,17 @@ import (
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.Disks)
|
||||
cmd.List(&compute_options.DiskListOptions{})
|
||||
cmd.Show(&compute_options.DiskIdOptions{})
|
||||
cmd.Perform("public", &compute_options.DiskIdOptions{})
|
||||
cmd.Perform("private", &compute_options.DiskIdOptions{})
|
||||
cmd.Perform("syncstatus", &compute_options.DiskIdOptions{})
|
||||
cmd.Perform("change-owner-candidate-domains", &compute_options.DiskIdOptions{})
|
||||
cmd.Perform("disk-cancel-delete", &compute_options.DiskIdOptions{})
|
||||
cmd.Perform("set-class-metadata", &options.ResourceMetadataOptions{})
|
||||
cmd.Perform("rebuild", &options.ResourceIdOptions{})
|
||||
cmd.Perform("migrate", &compute_options.DiskMigrateOptions{})
|
||||
cmd.Perform("change-billing-type", new(compute_options.DiskChangeBillingTypeOptions))
|
||||
|
||||
type DiskDetailOptions struct {
|
||||
ID string `help:"ID or Name of disk"`
|
||||
}
|
||||
R(&DiskDetailOptions{}, "disk-show", "Show details of disk", func(s *mcclient.ClientSession, args *DiskDetailOptions) error {
|
||||
disk, e := modules.Disks.Get(s, args.ID, nil)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printObject(disk)
|
||||
return nil
|
||||
})
|
||||
R(&DiskDetailOptions{}, "disk-cancel-delete", "Cancel pending delete disks", func(s *mcclient.ClientSession, args *DiskDetailOptions) error {
|
||||
disk, e := modules.Disks.PerformAction(s, args.ID, "cancel-delete", nil)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printObject(disk)
|
||||
return nil
|
||||
})
|
||||
cmd.Perform("change-storage-type", &compute_options.DiskChangeStorageTypeOptions{})
|
||||
|
||||
type DiskDeleteOptions struct {
|
||||
ID []string `help:"ID of disks to delete" metavar:"DISK"`
|
||||
@@ -95,25 +82,7 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&DiskDetailOptions{}, "disk-public", "Make a disk public", func(s *mcclient.ClientSession, args *DiskDetailOptions) error {
|
||||
disk, e := modules.Disks.PerformAction(s, args.ID, "public", nil)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printObject(disk)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&DiskDetailOptions{}, "disk-private", "Make a disk private", func(s *mcclient.ClientSession, args *DiskDetailOptions) error {
|
||||
disk, e := modules.Disks.PerformAction(s, args.ID, "private", nil)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printObject(disk)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&DiskDetailOptions{}, "disk-metadata", "Get metadata of a disk", func(s *mcclient.ClientSession, args *DiskDetailOptions) error {
|
||||
R(&compute_options.DiskIdOptions{}, "disk-metadata", "Get metadata of a disk", func(s *mcclient.ClientSession, args *compute_options.DiskIdOptions) error {
|
||||
meta, e := modules.Disks.GetMetadata(s, args.ID, nil)
|
||||
if e != nil {
|
||||
return e
|
||||
@@ -122,15 +91,6 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&DiskDetailOptions{}, "disk-syncstatus", "Sync status for disk", func(s *mcclient.ClientSession, args *DiskDetailOptions) error {
|
||||
ret, e := modules.Disks.PerformAction(s, args.ID, "syncstatus", nil)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printObject(ret)
|
||||
return nil
|
||||
})
|
||||
|
||||
type DiskUpdateOptions struct {
|
||||
ID string `help:"ID or name of disk"`
|
||||
Name string `help:"New name of disk"`
|
||||
@@ -299,7 +259,7 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&DiskDetailOptions{}, "disk-change-owner-candidate-domains", "Get change owner candidate domain list", func(s *mcclient.ClientSession, args *DiskDetailOptions) error {
|
||||
R(&compute_options.DiskIdOptions{}, "disk-change-owner-candidate-domains", "Get change owner candidate domain list", func(s *mcclient.ClientSession, args *compute_options.DiskIdOptions) error {
|
||||
result, err := modules.Disks.GetSpecific(s, args.ID, "change-owner-candidate-domains", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -333,6 +333,7 @@ func init() {
|
||||
IpAddr string `help:"IP address"`
|
||||
Bridge string `help:"Bridge of hostwire"`
|
||||
Interface string `help:"Interface name, eg:eth0, en0"`
|
||||
VlanId int `help:"Vlan ID"`
|
||||
}
|
||||
R(&HostAddNetIfOptions{}, "host-add-netif", "Host add a NIC", func(s *mcclient.ClientSession, args *HostAddNetIfOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
@@ -352,6 +353,7 @@ func init() {
|
||||
if len(args.Interface) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Interface), "interface")
|
||||
}
|
||||
addVlanIdToParams(params, args.VlanId)
|
||||
result, err := modules.Hosts.PerformAction(s, args.ID, "add-netif", params)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -361,12 +363,14 @@ func init() {
|
||||
})
|
||||
|
||||
type HostRemoveNetIfOptions struct {
|
||||
ID string `help:"ID or Name of host"`
|
||||
MAC string `help:"MAC of NIC to remove"`
|
||||
ID string `help:"ID or Name of host"`
|
||||
MAC string `help:"MAC of NIC to remove"`
|
||||
VlanId int `help:"Vlan Id"`
|
||||
}
|
||||
R(&HostRemoveNetIfOptions{}, "host-remove-netif", "Remove NIC from host", func(s *mcclient.ClientSession, args *HostRemoveNetIfOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(args.MAC), "mac")
|
||||
addVlanIdToParams(params, args.VlanId)
|
||||
result, err := modules.Hosts.PerformAction(s, args.ID, "remove-netif", params)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -381,6 +385,7 @@ func init() {
|
||||
Ip string `help:"IP address"`
|
||||
Network string `help:"network to connect"`
|
||||
Reserved bool `help:"fetch IP from reserved pool"`
|
||||
VlanId int `help:"Vlan ID"`
|
||||
}
|
||||
R(&HostEnableNetIfOptions{}, "host-enable-netif", "Enable a network interface for a host", func(s *mcclient.ClientSession, args *HostEnableNetIfOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
@@ -394,6 +399,7 @@ func init() {
|
||||
if len(args.Network) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Network), "network")
|
||||
}
|
||||
addVlanIdToParams(params, args.VlanId)
|
||||
result, err := modules.Hosts.PerformAction(s, args.ID, "enable-netif", params)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -406,6 +412,7 @@ func init() {
|
||||
ID string `help:"ID or Name of host"`
|
||||
MAC string `help:"MAC of NIC to disable"`
|
||||
Reserve bool `help:"Reserve the IP address"`
|
||||
VlanId int `help:"Vlan Id"`
|
||||
}
|
||||
R(&HostDisableNetIfOptions{}, "host-disable-netif", "Disable a network interface", func(s *mcclient.ClientSession, args *HostDisableNetIfOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
@@ -413,6 +420,7 @@ func init() {
|
||||
if args.Reserve {
|
||||
params.Add(jsonutils.JSONTrue, "reserve")
|
||||
}
|
||||
addVlanIdToParams(params, args.VlanId)
|
||||
result, err := modules.Hosts.PerformAction(s, args.ID, "disable-netif", params)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -754,3 +762,9 @@ func init() {
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func addVlanIdToParams(params *jsonutils.JSONDict, vlanId int) {
|
||||
if vlanId > 1 {
|
||||
params.Add(jsonutils.NewInt(int64(vlanId)), "vlan_id")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&options.TagListOptions{}, "tag-list", "List tags", func(s *mcclient.ClientSession, opts *options.TagListOptions) error {
|
||||
R(&options.TagListOptions{}, "service-metadata-list", "List service metadata", func(s *mcclient.ClientSession, opts *options.TagListOptions) error {
|
||||
var mod modulebase.IResourceManager
|
||||
switch opts.Service {
|
||||
case "compute":
|
||||
|
||||
@@ -143,6 +143,9 @@ func init() {
|
||||
cmd.Get("sshport", new(options.ServerIdOptions))
|
||||
cmd.Get("qemu-info", new(options.ServerIdOptions))
|
||||
cmd.Get("hardware-info", new(options.ServerIdOptions))
|
||||
cmd.Get("screen-dump-show", new(options.ServerScreenDumpOptions))
|
||||
cmd.BatchPerform("screen-dump", new(options.ServerIdsOptions))
|
||||
cmd.Perform("set-network-num-queues", new(options.ServerSetNetworkNumQueues))
|
||||
|
||||
cmd.GetProperty(&options.ServerStatusStatisticsOptions{})
|
||||
cmd.GetProperty(&options.ServerProjectStatisticsOptions{})
|
||||
|
||||
23
cmd/climc/shell/compute/serverscreendumps.go
Normal file
23
cmd/climc/shell/compute/serverscreendumps.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type ServerScreenDumpListOptions struct {
|
||||
options.BaseListOptions
|
||||
Server string `help:"Id or name of server"`
|
||||
}
|
||||
|
||||
func (o *ServerScreenDumpListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(o), nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.ServerScreenDumps)
|
||||
cmd.List(new(ServerScreenDumpListOptions))
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
|
||||
func init() {
|
||||
type WorkerListOptions struct {
|
||||
ServiceType string `choices:"image|cloudid|cloudevent|devtool|ansible|identity|notify|log|compute|compute_v2"`
|
||||
ServiceType string `choices:"image|cloudid|cloudevent|devtool|ansible|identity|notify|log|compute|compute_v2|meter|suggestion|cloudmon|cloudproxy|dns|monitor|scheduler|vpcagent|webconsole|yunionconf|bastionhost|extdb|yunionapi|report"`
|
||||
}
|
||||
R(&WorkerListOptions{}, "worker-list", "List workers", func(s *mcclient.ClientSession, args *WorkerListOptions) error {
|
||||
result, err := modules.Workers.List(s, jsonutils.Marshal(args))
|
||||
|
||||
@@ -83,6 +83,10 @@ func doK8sEventList(s *mcclient.ClientSession, args *EventListOptions) error {
|
||||
return DoEventList(*k8s.Logs.ResourceManager, s, args)
|
||||
}
|
||||
|
||||
func doHostDmesgList(s *mcclient.ClientSession, args *EventListOptions) error {
|
||||
return DoEventList(modules.DmesgLogs, s, args)
|
||||
}
|
||||
|
||||
func DoEventList(man modulebase.ResourceManager, s *mcclient.ClientSession, args *EventListOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
if len(args.Type) > 0 {
|
||||
@@ -157,6 +161,7 @@ func init() {
|
||||
R(&EventListOptions{}, "monitor-event-show", "Show operation event logs", doMonitorEventList)
|
||||
R(&EventListOptions{}, "notify-event-show", "Show operation event logs", doNotifyEventList)
|
||||
R(&EventListOptions{}, "kube-event-show", "Show operation event logs", doK8sEventList)
|
||||
R(&EventListOptions{}, "host-dmesg-show", "Show host dmesgs", doHostDmesgList)
|
||||
|
||||
R(&TypeEventListOptions{}, "server-event", "Show operation event logs of server", func(s *mcclient.ClientSession, args *TypeEventListOptions) error {
|
||||
nargs := EventListOptions{BaseEventListOptions: args.BaseEventListOptions, Id: args.ID, Type: []string{"server"}}
|
||||
|
||||
@@ -28,6 +28,7 @@ func init() {
|
||||
MODULE string `help:"module name"`
|
||||
FIELD string `help:"distinct field name to query"`
|
||||
Extra bool `help:"query extra distinct field"`
|
||||
Scope string `help:"resource scope" choices:"system|domain|project"`
|
||||
}
|
||||
R(&DistinctFieldOption{}, "distinct-field", "Query values of a distinct field for a module", func(s *mcclient.ClientSession, args *DistinctFieldOption) error {
|
||||
mod, err := modulebase.GetModule(s, args.MODULE)
|
||||
@@ -43,6 +44,9 @@ func init() {
|
||||
} else {
|
||||
params.Add(jsonutils.NewString(args.FIELD), "field")
|
||||
}
|
||||
if len(args.Scope) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Scope), "scope")
|
||||
}
|
||||
result, err := mod.Get(s, "distinct-field", params)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -56,6 +60,7 @@ func init() {
|
||||
Field []string `help:"distinct field name to query"`
|
||||
ExtraField []string `help:"distinct field name to query"`
|
||||
ExtraResource string
|
||||
Scope string `help:"resource scope" choices:"system|domain|project"`
|
||||
}
|
||||
R(&DistinctFieldsOption{}, "distinct-fields", "Query values of a distinct fields for a module", func(s *mcclient.ClientSession, args *DistinctFieldsOption) error {
|
||||
mod, err := modulebase.GetModule(s, args.MODULE)
|
||||
|
||||
37
cmd/climc/shell/misc/history_data_clean.go
Normal file
37
cmd/climc/shell/misc/history_data_clean.go
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package misc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type HistoryDataCleanOptions struct {
|
||||
SERVICE string `help:"Service type"`
|
||||
Day *int `default:"30"`
|
||||
}
|
||||
R(&HistoryDataCleanOptions{}, "history-data-clean", "clean history data", func(s *mcclient.ClientSession, args *HistoryDataCleanOptions) error {
|
||||
body, err := modules.HistoryDataClean(s, args.SERVICE, args.Day)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(body.PrettyString())
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -38,6 +38,23 @@ func init() {
|
||||
Service string `help:"Service type"`
|
||||
Address string `help:"Service listen address"`
|
||||
Gc bool `help:"run GC before taking the heap sample"`
|
||||
Output string `help:"Save pprof file to specified path instead of opening with go tool" short-token:"o"`
|
||||
}
|
||||
|
||||
writeReaderToFile := func(input io.Reader, file *os.File) error {
|
||||
if _, err := io.Copy(file, input); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
downloadToFile := func(input io.Reader, filepath string) error {
|
||||
file, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
return writeReaderToFile(input, file)
|
||||
}
|
||||
|
||||
downloadToTemp := func(input io.Reader, pattern string) (string, error) {
|
||||
@@ -46,7 +63,7 @@ func init() {
|
||||
return "", err
|
||||
}
|
||||
defer tmpfile.Close()
|
||||
if _, err := io.Copy(tmpfile, input); err != nil {
|
||||
if err := writeReaderToFile(input, tmpfile); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return tmpfile.Name(), nil
|
||||
@@ -83,6 +100,15 @@ func init() {
|
||||
return err
|
||||
}
|
||||
|
||||
// If output path is specified, save file and return
|
||||
if len(opts.Output) > 0 {
|
||||
if err := downloadToFile(src, opts.Output); err != nil {
|
||||
return errors.Wrapf(err, "save pprof file to %s", opts.Output)
|
||||
}
|
||||
fmt.Printf("pprof file saved to: %s\n", opts.Output)
|
||||
return nil
|
||||
}
|
||||
|
||||
tempfile, err := downloadToTemp(src, pType)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -34,7 +34,7 @@ type CommonAlertTerm struct {
|
||||
Comparator string
|
||||
Threshold float64
|
||||
Filters []monitorapi.MetricQueryTag
|
||||
FieldOpt string
|
||||
FieldOpt monitorapi.CommonAlertFieldOpt
|
||||
Name string
|
||||
ConditionType string
|
||||
From string
|
||||
@@ -94,7 +94,7 @@ func newCommonAlertQuery(tem *CommonAlertTerm) *monitorapi.CommonAlertQuery {
|
||||
Operator: tem.Operator,
|
||||
}
|
||||
if tem.FieldOpt != "" {
|
||||
commonAlert.FieldOpt = monitorapi.CommonAlertFieldOpt_Division
|
||||
commonAlert.FieldOpt = monitorapi.CommonAlertFieldOptDivision
|
||||
}
|
||||
if len(tem.ConditionType) != 0 {
|
||||
commonAlert.ConditionType = tem.ConditionType
|
||||
|
||||
@@ -16,6 +16,9 @@ package notify
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
identity_api "yunion.io/x/onecloud/pkg/apis/identity"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
identity_modules "yunion.io/x/onecloud/pkg/mcclient/modules/identity"
|
||||
modules "yunion.io/x/onecloud/pkg/mcclient/modules/notify"
|
||||
options "yunion.io/x/onecloud/pkg/mcclient/options/notify"
|
||||
)
|
||||
@@ -36,4 +39,32 @@ func init() {
|
||||
cmd.PerformClass("get-types", new(options.ReceiverGetTypeOptions))
|
||||
cmd.Perform("get-subscription", new(options.ReceiverGetSubscriptionOptions))
|
||||
cmd.GetProperty(new(options.SReceiverRoleContactType))
|
||||
|
||||
type SyncUserContactOptions struct {
|
||||
USERID string `json:"user_id"`
|
||||
Mobile string `json:"mobile"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
R(&SyncUserContactOptions{}, "sync-user-contacts", "Sync user contact", func(s *mcclient.ClientSession, args *SyncUserContactOptions) error {
|
||||
userObj, err := identity_modules.UsersV3.Get(s, args.USERID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
user := identity_api.UserDetails{}
|
||||
err = userObj.Unmarshal(&user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(args.Mobile) == 0 {
|
||||
args.Mobile = user.Mobile
|
||||
}
|
||||
if len(args.Email) == 0 {
|
||||
args.Email = user.Email
|
||||
}
|
||||
err = modules.NotifyReceiver.SyncUserContact(s, user.Id, args.Mobile, args.Email)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
87
cmd/isocli/main.go
Normal file
87
cmd/isocli/main.go
Normal file
@@ -0,0 +1,87 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"yunion.io/x/pkg/util/shellutils"
|
||||
"yunion.io/x/structarg"
|
||||
|
||||
_ "yunion.io/x/onecloud/cmd/isocli/shell"
|
||||
)
|
||||
|
||||
type BaseOptions struct {
|
||||
Debug bool `help:"debug mode"`
|
||||
SUBCOMMAND string `help:"aliyuncli subcommand" subcommand:"true"`
|
||||
}
|
||||
|
||||
func getSubcommandParser() (*structarg.ArgumentParser, error) {
|
||||
parse, e := structarg.NewArgumentParserWithHelp(&BaseOptions{},
|
||||
"isocli",
|
||||
"Command-line ISO tools.",
|
||||
`See "isocli COMMAND --help" for help on a specific command.`)
|
||||
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
|
||||
subcmd := parse.GetSubcommand()
|
||||
if subcmd == nil {
|
||||
return nil, fmt.Errorf("No subcommand argument.")
|
||||
}
|
||||
for _, v := range shellutils.CommandTable {
|
||||
_, e := subcmd.AddSubParserWithHelp(v.Options, v.Command, v.Desc, v.Callback)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
}
|
||||
return parse, nil
|
||||
}
|
||||
|
||||
func showErrorAndExit(e error) {
|
||||
fmt.Fprintf(os.Stderr, "%s", e)
|
||||
fmt.Fprintln(os.Stderr)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func main() {
|
||||
parser, e := getSubcommandParser()
|
||||
if e != nil {
|
||||
showErrorAndExit(e)
|
||||
}
|
||||
e = parser.ParseArgs(os.Args[1:], false)
|
||||
|
||||
if parser.IsHelpSet() {
|
||||
fmt.Print(parser.HelpString())
|
||||
return
|
||||
}
|
||||
subcmd := parser.GetSubcommand()
|
||||
subparser := subcmd.GetSubParser()
|
||||
if e != nil || subparser == nil {
|
||||
if subparser != nil {
|
||||
fmt.Print(subparser.Usage())
|
||||
} else {
|
||||
fmt.Print(parser.Usage())
|
||||
}
|
||||
showErrorAndExit(e)
|
||||
}
|
||||
suboptions := subparser.Options()
|
||||
e = subcmd.Invoke(suboptions)
|
||||
if e != nil {
|
||||
showErrorAndExit(e)
|
||||
}
|
||||
}
|
||||
82
cmd/isocli/shell/iso.go
Normal file
82
cmd/isocli/shell/iso.go
Normal file
@@ -0,0 +1,82 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/util/shellutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/util/isoutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type DetectOSOptions struct {
|
||||
ISO string `help:"ISO file"`
|
||||
}
|
||||
shellutils.R(&DetectOSOptions{}, "detect", "Detect", func(args *DetectOSOptions) error {
|
||||
stat, err := os.Stat(args.ISO)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if stat.IsDir() {
|
||||
// 如果是目录,仅遍历一层目录下的 .iso 文件
|
||||
entries, err := os.ReadDir(args.ISO)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
continue // 跳过子目录
|
||||
}
|
||||
if strings.HasSuffix(strings.ToLower(entry.Name()), ".iso") {
|
||||
path := filepath.Join(args.ISO, entry.Name())
|
||||
fmt.Printf("Processing: %s\n", path)
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
fmt.Printf("Error opening %s: %v\n", path, err)
|
||||
continue // 继续处理其他文件
|
||||
}
|
||||
isoInfo, err := isoutils.DetectOSFromISO(f)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
fmt.Printf("Error detecting OS from %s: %v\n", path, err)
|
||||
continue
|
||||
}
|
||||
fmt.Printf("%s: %s\n", path, jsonutils.Marshal(isoInfo))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 如果是文件,按原逻辑处理
|
||||
f, err := os.Open(args.ISO)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
isoInfo, err := isoutils.DetectOSFromISO(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("%s: %s\n", args.ISO, jsonutils.Marshal(isoInfo))
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -164,19 +164,32 @@ func (c *RaidInfoCollector) toTelegrafReportData(raidDiskInfo []*baremetal.Barem
|
||||
tag := fmt.Sprintf("%s=%s,%s=%s", "hostname", c.Hostname, "host_ip", c.HostIp)
|
||||
ret := []string{}
|
||||
for i := 0; i < len(raidDiskInfo); i++ {
|
||||
statArr := []string{}
|
||||
fieldArr := []string{}
|
||||
tagArr := []string{}
|
||||
raidDiskInfo[i].Status = strings.ToLower(raidDiskInfo[i].Status)
|
||||
jStat := jsonutils.Marshal(raidDiskInfo[i])
|
||||
jMap, _ := jStat.GetMap()
|
||||
for k, v := range jMap {
|
||||
statArr = append(statArr, fmt.Sprintf("%s=%s", k, v.String()))
|
||||
vStr, _ := v.GetString()
|
||||
if vStr == "" {
|
||||
continue
|
||||
}
|
||||
vStr = strings.ReplaceAll(vStr, " ", "\\ ")
|
||||
kv := fmt.Sprintf("%s=%s", k, vStr)
|
||||
switch k {
|
||||
case "adapter", "slot":
|
||||
fieldArr = append(fieldArr, kv)
|
||||
case "model", "driver", "status":
|
||||
tagArr = append(tagArr, kv)
|
||||
case "index":
|
||||
continue
|
||||
default:
|
||||
tagArr = append(tagArr, kv)
|
||||
}
|
||||
}
|
||||
stat := strings.Join(statArr, ",")
|
||||
diskTag := fmt.Sprintf(
|
||||
"%s,%s=%s,%s=%d,%s=%d", tag, "driver", raidDiskInfo[i].Driver,
|
||||
"adapter", raidDiskInfo[i].Adapter, "slot", raidDiskInfo[i].Slot,
|
||||
)
|
||||
line := fmt.Sprintf("%s,%s %s", MEASUREMENT, diskTag, stat)
|
||||
field := strings.Join(fieldArr, ",")
|
||||
diskTag := tag + "," + strings.Join(tagArr, ",")
|
||||
line := fmt.Sprintf("%s,%s %s", MEASUREMENT, diskTag, field)
|
||||
ret = append(ret, line)
|
||||
}
|
||||
return strings.Join(ret, "\n")
|
||||
@@ -185,7 +198,7 @@ func (c *RaidInfoCollector) toTelegrafReportData(raidDiskInfo []*baremetal.Barem
|
||||
func (c *RaidInfoCollector) reportRaidInfoToTelegraf(data string) {
|
||||
body := strings.NewReader(data)
|
||||
res, err := httputils.Request(
|
||||
httputils.GetDefaultClient(), context.Background(), "POST", TelegrafServer, nil, body, false)
|
||||
httputils.GetDefaultClient(), context.Background(), "POST", TelegrafServer, nil, body, true)
|
||||
if err != nil {
|
||||
log.Errorf("Upload guest metric failed: %s", err)
|
||||
return
|
||||
|
||||
30
go.mod
30
go.mod
@@ -6,6 +6,7 @@ require (
|
||||
bazil.org/fuse v0.0.0-20180421153158-65cc252bf669
|
||||
github.com/360EntSecGroup-Skylar/excelize v1.4.0
|
||||
github.com/LeeEirc/terminalparser v0.0.0-20240205084113-fbf78c8480f2
|
||||
github.com/Microsoft/go-winio v0.6.2
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.684
|
||||
github.com/anacrolix/torrent v0.0.0-20181129073333-cc531b8c4a80
|
||||
github.com/benbjohnson/clock v1.0.0
|
||||
@@ -23,6 +24,7 @@ require (
|
||||
github.com/go-yaml/yaml v2.1.0+incompatible
|
||||
github.com/golang-plus/uuid v1.0.0
|
||||
github.com/golang/mock v1.4.4
|
||||
github.com/golang/protobuf v1.5.3
|
||||
github.com/google/gopacket v1.1.17
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/googollee/go-socket.io v0.0.0-20181214084611-0ad7206c347a
|
||||
@@ -33,6 +35,7 @@ require (
|
||||
github.com/influxdata/influxql v1.1.0
|
||||
github.com/influxdata/promql/v2 v2.12.0
|
||||
github.com/jaypipes/ghw v0.11.0
|
||||
github.com/kdomanski/iso9660 v0.4.0
|
||||
github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c
|
||||
github.com/lestrrat-go/jwx v1.0.2
|
||||
github.com/lestrrat/go-jwx v0.0.0-20180221005942-b7d4802280ae
|
||||
@@ -44,6 +47,7 @@ require (
|
||||
github.com/mholt/caddy v0.10.11
|
||||
github.com/miekg/dns v1.1.25
|
||||
github.com/minio/minio-go v6.0.14+incompatible
|
||||
github.com/mogaika/udf v0.0.0-20171019171931-167f0ab01c73
|
||||
github.com/petermattis/goid v0.0.0-20250508124226-395b08cebbdb
|
||||
github.com/pierrec/lz4/v4 v4.1.15
|
||||
github.com/pkg/errors v0.9.1
|
||||
@@ -55,7 +59,7 @@ require (
|
||||
github.com/sevlyar/go-daemon v0.1.5
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible
|
||||
github.com/shirou/gopsutil/v3 v3.22.10
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9
|
||||
github.com/smartystreets/goconvey v1.7.2
|
||||
github.com/stretchr/testify v1.9.0
|
||||
@@ -66,6 +70,7 @@ require (
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible
|
||||
github.com/xuri/excelize/v2 v2.7.1
|
||||
github.com/zeebo/xxh3 v1.0.2
|
||||
github.com/zexi/influxql-to-metricsql v0.1.1
|
||||
go.etcd.io/etcd/api/v3 v3.5.0
|
||||
go.etcd.io/etcd/client/v3 v3.5.0
|
||||
@@ -80,6 +85,7 @@ require (
|
||||
google.golang.org/grpc v1.62.0
|
||||
google.golang.org/protobuf v1.32.0
|
||||
gopkg.in/fatih/set.v0 v0.2.1
|
||||
gopkg.in/ini.v1 v1.62.0
|
||||
gopkg.in/mail.v2 v2.3.1
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
k8s.io/api v0.19.3
|
||||
@@ -87,14 +93,14 @@ require (
|
||||
k8s.io/client-go v0.19.3
|
||||
k8s.io/cluster-bootstrap v0.19.3
|
||||
moul.io/http2curl/v2 v2.3.0
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250924031624-e6936c793c60
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260207043119-2907d68518c5
|
||||
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0
|
||||
yunion.io/x/jsonutils v1.0.1-0.20250507052344-1abcf4f443b1
|
||||
yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91
|
||||
yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900
|
||||
yunion.io/x/pkg v1.10.4-0.20250820035218-6008459eb4f0
|
||||
yunion.io/x/pkg v1.10.4-0.20260127060125-8939521ef75e
|
||||
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1
|
||||
yunion.io/x/sqlchemy v1.1.3-0.20250923143347-b98e89dbc372
|
||||
yunion.io/x/sqlchemy v1.1.3-0.20251231025938-b0a38f6e9fab
|
||||
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c
|
||||
)
|
||||
|
||||
@@ -105,8 +111,6 @@ require (
|
||||
cloud.google.com/go/iam v1.1.6 // indirect
|
||||
cloud.google.com/go/storage v1.39.1 // indirect
|
||||
gitee.com/chunanyong/dm v1.8.14 // indirect
|
||||
github.com/Azure/azure-sdk-for-go v36.1.0+incompatible // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
github.com/Azure/go-autorest/autorest v0.9.6 // indirect
|
||||
github.com/Azure/go-autorest/autorest/adal v0.8.2 // indirect
|
||||
github.com/Azure/go-autorest/autorest/azure/auth v0.4.2 // indirect
|
||||
@@ -117,8 +121,7 @@ require (
|
||||
github.com/ClickHouse/clickhouse-go v1.5.4 // indirect
|
||||
github.com/DataDog/dd-trace-go v0.6.1 // indirect
|
||||
github.com/DataDog/zstd v1.3.4 // indirect
|
||||
github.com/Microsoft/azure-vhd-utils v0.0.0-20181115010904-44cbada2ece3 // indirect
|
||||
github.com/RoaringBitmap/roaring v0.4.16 // indirect
|
||||
github.com/RoaringBitmap/roaring v1.2.3 // indirect
|
||||
github.com/Shopify/sarama v1.20.0 // indirect
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible // indirect
|
||||
github.com/StackExchange/wmi v1.2.1 // indirect
|
||||
@@ -137,6 +140,7 @@ require (
|
||||
github.com/basgys/goxml2json v1.1.1-0.20181031222924-996d9fc8d313 // indirect
|
||||
github.com/beevik/etree v1.1.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.2.0 // indirect
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
|
||||
github.com/boltdb/bolt v1.3.1 // indirect
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||
@@ -162,7 +166,6 @@ require (
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect
|
||||
github.com/frankban/quicktest v1.14.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
|
||||
github.com/go-logfmt/logfmt v0.5.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
@@ -176,7 +179,6 @@ require (
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-plus/errors v1.0.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/go-querystring v1.0.0 // indirect
|
||||
@@ -197,6 +199,7 @@ require (
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/jtolds/gls v4.20.0+incompatible // indirect
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/ks3sdklib/aws-sdk-go v1.8.1 // indirect
|
||||
github.com/leodido/go-urn v1.2.0 // indirect
|
||||
@@ -220,13 +223,12 @@ require (
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/mozillazg/go-httpheader v0.2.1 // indirect
|
||||
github.com/mozillazg/go-pinyin v0.19.0 // indirect
|
||||
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae // indirect
|
||||
github.com/mschoch/smat v0.2.0 // indirect
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 // indirect
|
||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 // indirect
|
||||
github.com/opentracing/opentracing-go v1.0.2 // indirect
|
||||
github.com/openzipkin/zipkin-go-opentracing v0.3.4 // indirect
|
||||
github.com/oracle/oci-go-sdk v24.3.0+incompatible // indirect
|
||||
github.com/philhofer/fwd v1.0.0 // indirect
|
||||
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
|
||||
github.com/pkg/term v1.0.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
@@ -247,7 +249,6 @@ require (
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.413 // indirect
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.7.24 // indirect
|
||||
github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e // indirect
|
||||
github.com/tinylib/msgp v1.1.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
||||
github.com/tklauser/numcpus v0.4.0 // indirect
|
||||
github.com/ugorji/go/codec v1.1.7 // indirect
|
||||
@@ -279,7 +280,6 @@ require (
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240228224816-df926f6c8641 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/klog/v2 v2.20.0 // indirect
|
||||
k8s.io/utils v0.0.0-20200729134348-d5654de09c73 // indirect
|
||||
@@ -288,5 +288,3 @@ require (
|
||||
)
|
||||
|
||||
replace github.com/influxdata/promql/v2 => github.com/zexi/promql/v2 v2.12.1
|
||||
|
||||
replace github.com/Azure/azure-sdk-for-go => github.com/Azure/azure-sdk-for-go v36.1.0+incompatible
|
||||
|
||||
53
go.sum
53
go.sum
@@ -48,10 +48,6 @@ gitee.com/chunanyong/dm v1.8.14 h1:1S9+aD0fY/HXkcm8dKh2HjYsDlcdXNG+4IOX9JtrSjA=
|
||||
gitee.com/chunanyong/dm v1.8.14/go.mod h1:EPRJnuPFgbyOFgJ0TRYCTGzhq+ZT4wdyaj/GW/LLcNg=
|
||||
github.com/360EntSecGroup-Skylar/excelize v1.4.0 h1:43rak9uafmwSJpXfFO1heKQph8tP3nlfWJWFQQtW1R0=
|
||||
github.com/360EntSecGroup-Skylar/excelize v1.4.0/go.mod h1:R8KYLmGns0vDPe6/HyphW0mzW+MFexlGDafU0ykVEnU=
|
||||
github.com/Azure/azure-sdk-for-go v36.1.0+incompatible h1:smHlbChr/JDmsyUqELZXLs0YIgpXecIGdUibuc2983s=
|
||||
github.com/Azure/azure-sdk-for-go v36.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
|
||||
github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0=
|
||||
github.com/Azure/go-autorest/autorest v0.9.6 h1:5YWtOnckcudzIw8lPPBcWOnmIFWMtHci1ZWAZulMSx0=
|
||||
@@ -72,8 +68,6 @@ github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxB
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
|
||||
github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk=
|
||||
github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
|
||||
github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY=
|
||||
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
|
||||
github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k=
|
||||
@@ -88,8 +82,8 @@ github.com/DataDog/zstd v1.3.4 h1:LAGHkXuvC6yky+C2CUG2tD7w8QlrUwpue8XwIh0X4AY=
|
||||
github.com/DataDog/zstd v1.3.4/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||
github.com/LeeEirc/terminalparser v0.0.0-20240205084113-fbf78c8480f2 h1:XGB3B0651J1uKOE1KJa1gsrV/DO1kthhk2NTDUHATgs=
|
||||
github.com/LeeEirc/terminalparser v0.0.0-20240205084113-fbf78c8480f2/go.mod h1:tiLv6VBLH4Z3KdBSe2qIKRwQDGCVQ9/F5fOKpQGvyoA=
|
||||
github.com/Microsoft/azure-vhd-utils v0.0.0-20181115010904-44cbada2ece3 h1:gImoAO1xAcC1oDlYmD/X7dggsodGf2DFJOVE5m0ssms=
|
||||
github.com/Microsoft/azure-vhd-utils v0.0.0-20181115010904-44cbada2ece3/go.mod h1:u0H9gMieFLxkUy8RS0X8VbFWyPs2815qQAaitRbj6x0=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
@@ -97,8 +91,8 @@ github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
|
||||
github.com/RoaringBitmap/roaring v0.4.7/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w=
|
||||
github.com/RoaringBitmap/roaring v0.4.16 h1:NholfewybRLOwACgfqfzn/N5xa6keKNs4fP00t0cwLo=
|
||||
github.com/RoaringBitmap/roaring v0.4.16/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w=
|
||||
github.com/RoaringBitmap/roaring v1.2.3 h1:yqreLINqIrX22ErkKI0vY47/ivtJr6n+kMhVOVmhWBY=
|
||||
github.com/RoaringBitmap/roaring v1.2.3/go.mod h1:plvDsJQpxOC5bw8LRteu/MLWHsHez/3y6cubLI4/1yE=
|
||||
github.com/Shopify/sarama v1.20.0 h1:wAMHhl1lGRlobeoV/xOKpbqD2OQsOvY4A/vIOGroIe8=
|
||||
github.com/Shopify/sarama v1.20.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc=
|
||||
@@ -173,6 +167,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y=
|
||||
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
|
||||
github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA=
|
||||
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||
github.com/bkaradzic/go-lz4 v1.0.0 h1:RXc4wYsyz985CkXXeX04y4VnZFGG8Rd43pRaHsOXAKk=
|
||||
github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
||||
@@ -222,8 +218,6 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumC
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4=
|
||||
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
|
||||
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
|
||||
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
||||
github.com/dnstap/golang-dnstap v0.0.0-20170829151710-2cf77a2b5e11 h1:m8nX8hsUghn853BJ5qB0lX+VvS6LTJPksWyILFZRYN4=
|
||||
github.com/dnstap/golang-dnstap v0.0.0-20170829151710-2cf77a2b5e11/go.mod h1:s1PfVYYVmTMgCSPtho4LKBDecEHJWtiVDPNv78Z985U=
|
||||
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||
@@ -277,9 +271,6 @@ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm
|
||||
github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
|
||||
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
|
||||
github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
|
||||
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2 h1:Ujru1hufTHVb++eG6OuNDKMxZnGIvF6o/u8q/8h2+I4=
|
||||
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
|
||||
github.com/glycerine/goconvey v0.0.0-20180728074245-46e3a41ad493 h1:OTanQnFt0bi5iLFSdbEVA/idR6Q2WhCm+deb7ir2CcM=
|
||||
github.com/glycerine/goconvey v0.0.0-20180728074245-46e3a41ad493/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
|
||||
github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
|
||||
@@ -496,9 +487,13 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
|
||||
github.com/kdomanski/iso9660 v0.4.0 h1:BPKKdcINz3m0MdjIMwS0wx1nofsOjxOq8TOr45WGHFg=
|
||||
github.com/kdomanski/iso9660 v0.4.0/go.mod h1:OxUSupHsO9ceI8lBLPJKWBTphLemjrCQY8LPXM7qSzU=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c h1:N7A4JCA2G+j5fuFxCsJqjFU/sZe0mj8H0sSoSwbaikw=
|
||||
github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c/go.mod h1:Nn5wlyECw3iJrzi0AhIWg+AJUb4PlRQVW4/3XHH1LZA=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
@@ -593,14 +588,17 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/mogaika/udf v0.0.0-20171019171931-167f0ab01c73 h1:HpHNB68mF30LkUorpr7B22Xy0XwParP/n+AL0z4VlFc=
|
||||
github.com/mogaika/udf v0.0.0-20171019171931-167f0ab01c73/go.mod h1:OVErfG87tRGCHZpQGO8pL4vDZuY0qr4blPOTR0go6e8=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||
github.com/mozillazg/go-httpheader v0.2.1 h1:geV7TrjbL8KXSyvghnFm+NyTux/hxwueTSrwhe88TQQ=
|
||||
github.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60=
|
||||
github.com/mozillazg/go-pinyin v0.19.0 h1:p+J8/kjJ558KPvVGYLvqBhxf8jbZA2exSLCs2uUVN8c=
|
||||
github.com/mozillazg/go-pinyin v0.19.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc=
|
||||
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae h1:VeRdUYdCw49yizlSbMEn2SZ+gT+3IUKx8BqxyQdz+BY=
|
||||
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg=
|
||||
github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM=
|
||||
github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw=
|
||||
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
@@ -623,7 +621,6 @@ github.com/oracle/oci-go-sdk v24.3.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35uk
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/petermattis/goid v0.0.0-20250508124226-395b08cebbdb h1:3PrKuO92dUTMrQ9dx0YNejC6U/Si6jqKmyQ9vWjwqR4=
|
||||
github.com/petermattis/goid v0.0.0-20250508124226-395b08cebbdb/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
|
||||
github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ=
|
||||
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
|
||||
@@ -701,8 +698,9 @@ github.com/shirou/gopsutil/v3 v3.22.10/go.mod h1:QNza6r4YQoydyCfo6rH0blGfKahgibh
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9 h1:lpEzuenPuO1XNTeikEmvqYFcU37GVLl8SRNblzyvGBE=
|
||||
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9/go.mod h1:PLPIyL7ikehBD1OAjmKKiOEhbvWyHGaNDjquXMcYABo=
|
||||
github.com/smartystreets/assertions v0.0.0-20180607162144-eb5b59917fa2/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
@@ -749,8 +747,6 @@ github.com/tencentyun/cos-go-sdk-v5 v0.7.24/go.mod h1:wQBO5HdAkLjj2q6XQiIfDSP8DX
|
||||
github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e h1:T5PdfK/M1xyrHwynxMIVMWLS7f/qHwfslZphxtGnw7s=
|
||||
github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g=
|
||||
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||
github.com/tinylib/msgp v1.1.0 h1:9fQd+ICuRIu/ue4vxJZu6/LzxN0HwMds2nq/0cFvxHU=
|
||||
github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
|
||||
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
|
||||
github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
|
||||
@@ -797,6 +793,10 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
|
||||
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
||||
github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
|
||||
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
|
||||
github.com/zexi/influxql-to-metricsql v0.1.1 h1:dXnVzlxVLuo88zGkDca7erEnmvprGWjzsBcs8qIoQGQ=
|
||||
github.com/zexi/influxql-to-metricsql v0.1.1/go.mod h1:JlC5FY+6De9ZPxG47G5DOgva8P9X1VaKS4ExzCmhSCc=
|
||||
github.com/zexi/promql/v2 v2.12.1 h1:crHKpULdLLsBZ9b78Rg6qQkugzlk6BHeCj93tw/F5RU=
|
||||
@@ -1225,7 +1225,6 @@ gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk=
|
||||
gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
|
||||
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/urfave/cli.v1 v1.19.1/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
|
||||
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
@@ -1273,8 +1272,8 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250924031624-e6936c793c60 h1:TK1qL43Foc8T3L4cxE7psEYas66Pn4GfaaEZJE/zCmQ=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250924031624-e6936c793c60/go.mod h1:S9o/TRZsnYWGaGe7o3PpeOv6CgMY8ZJwITYsEnGfOgQ=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260207043119-2907d68518c5 h1:CqO2GuJk/pT4yjI3OTeLm+/mY1H+aUK+B6hxhzIdUQ4=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260207043119-2907d68518c5/go.mod h1:GdAwZ78fiqj13i2r1zNuE/D6YOlhh2q4jZjuyHiZTq8=
|
||||
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0 h1:msG4SiDSVU7CrXH06WuHlNEZXIooTcmNbfrIGHuIHBU=
|
||||
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
|
||||
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
|
||||
@@ -1288,11 +1287,11 @@ yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900 h1:Hu/4ERvoWaN6aiFs4h4/yvVB
|
||||
yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900/go.mod h1:0vLkNEhlmA64HViPBAnSTUMrx5QP1CLsxXmxDKQ80tc=
|
||||
yunion.io/x/pkg v0.0.0-20190620104149-945c25821dbf/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
|
||||
yunion.io/x/pkg v0.0.0-20190628082551-f4033ba2ea30/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
|
||||
yunion.io/x/pkg v1.10.4-0.20250820035218-6008459eb4f0 h1:/vHcYqzQInxqR1jjS+e7A0owRXj+/rvrIgES6uadUqs=
|
||||
yunion.io/x/pkg v1.10.4-0.20250820035218-6008459eb4f0/go.mod h1:0Bwxqd9MA3ACi119/l02FprY/o9gHahmYC2bsSbnVpM=
|
||||
yunion.io/x/pkg v1.10.4-0.20260127060125-8939521ef75e h1:py5Kd6cgP6pxB9pSc4ry/gnmA6rJZwMVOnAjra4sb2g=
|
||||
yunion.io/x/pkg v1.10.4-0.20260127060125-8939521ef75e/go.mod h1:0Bwxqd9MA3ACi119/l02FprY/o9gHahmYC2bsSbnVpM=
|
||||
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1 h1:1KJ3YYinydPHpDEQRXdr/T8SYcKZ5Er+m489H+PnaQ4=
|
||||
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1/go.mod h1:0iFKpOs1y4lbCxeOmq3Xx/0AcQoewVPwj62eRluioEo=
|
||||
yunion.io/x/sqlchemy v1.1.3-0.20250923143347-b98e89dbc372 h1:8lR9HzYTxSgxcVv6uC2Ogkk1Y3FEEanABfgeleCzhfA=
|
||||
yunion.io/x/sqlchemy v1.1.3-0.20250923143347-b98e89dbc372/go.mod h1:vCIZpqhZ5Jzaq3tFyrti/vv8BijQKtkzSgNT/uH4H5A=
|
||||
yunion.io/x/sqlchemy v1.1.3-0.20251231025938-b0a38f6e9fab h1:5m/bSzW3uTAk83rp9eethbYsxJFYInFVeU1RDkteW4E=
|
||||
yunion.io/x/sqlchemy v1.1.3-0.20251231025938-b0a38f6e9fab/go.mod h1:vCIZpqhZ5Jzaq3tFyrti/vv8BijQKtkzSgNT/uH4H5A=
|
||||
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c h1:QuLab2kSRECZRxo4Lo2KcYn6XjQFDGaZ1+x0pYDVVwQ=
|
||||
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c/go.mod h1:EP6NSv2C0zzqBDTKumv8hPWLb3XvgMZDHQRfyuOrQng=
|
||||
|
||||
@@ -74,7 +74,7 @@ func (app *Application) InitHandlers() *Application {
|
||||
if options.Options.EnableBackendServiceProxy {
|
||||
// bind backend service API proxy
|
||||
log.Infof("enable backend service proxy")
|
||||
app.BackendServiceProxyHandler = handler.NewBackendServiceProxyHandler("/api/s/<service>")
|
||||
app.BackendServiceProxyHandler = handler.NewBackendServiceProxyHandler("/api/s/<service>", options.Options.BackendProxyReadWorkerCount, options.Options.BackendProxyWriteWorkerCount)
|
||||
}
|
||||
|
||||
app.CloudIdSAMLHandler = handler.NewProxyHandlerWithService(cloudid.SAML_IDP_PREFIX, cloudid.SERVICE_TYPE)
|
||||
|
||||
@@ -17,7 +17,7 @@ package clientman
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
@@ -27,9 +27,9 @@ import (
|
||||
|
||||
func InitClient() error {
|
||||
if options.Options.EnableSsl {
|
||||
privData, err := ioutil.ReadFile(options.Options.SslKeyfile)
|
||||
privData, err := os.ReadFile(options.Options.SslKeyfile)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "ioutil.ReadFile %s", options.Options.SslKeyfile)
|
||||
return errors.Wrapf(err, "os.ReadFile %s", options.Options.SslKeyfile)
|
||||
}
|
||||
privateKey, err := seclib2.DecodePrivateKey(privData)
|
||||
if err != nil {
|
||||
|
||||
102
pkg/apigateway/handler/assume.go
Normal file
102
pkg/apigateway/handler/assume.go
Normal file
@@ -0,0 +1,102 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apigateway/clientman"
|
||||
"yunion.io/x/onecloud/pkg/appsrv"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/util/netutils2"
|
||||
)
|
||||
|
||||
const (
|
||||
ASSUME_TOKEN_HEADER = "X-Assume-Token"
|
||||
)
|
||||
|
||||
type SAssumeToken struct {
|
||||
Token string `json:"token"`
|
||||
UserId string `json:"user_id"`
|
||||
ProjectId string `json:"project_id"`
|
||||
}
|
||||
|
||||
func getAssumeToken(r *http.Request) (*SAssumeToken, error) {
|
||||
auth := r.Header.Get(ASSUME_TOKEN_HEADER)
|
||||
if auth == "" {
|
||||
return nil, errors.Wrap(httperrors.ErrInputParameter, "Assume token header is empty")
|
||||
}
|
||||
parts := strings.Split(strings.TrimSpace(auth), ":")
|
||||
if len(parts) != 3 {
|
||||
return nil, errors.Wrap(httperrors.ErrInputParameter, "Assume token header is invalid")
|
||||
}
|
||||
return &SAssumeToken{
|
||||
Token: parts[0],
|
||||
UserId: parts[1],
|
||||
ProjectId: parts[2],
|
||||
}, nil
|
||||
}
|
||||
|
||||
func doAssumeLogin(assumeToken *SAssumeToken, w http.ResponseWriter, req *http.Request) (mcclient.TokenCredential, error) {
|
||||
cliIp := netutils2.GetHttpRequestIp(req)
|
||||
token, err := auth.Client().AuthenticateAssume(assumeToken.Token, assumeToken.UserId, assumeToken.ProjectId, cliIp)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(httperrors.ErrInvalidCredential, "AuthenticateAssume fail %s", err)
|
||||
}
|
||||
authToken := clientman.NewAuthToken(token.GetTokenString(), false, false, false)
|
||||
saveLoginCookies(w, authToken, token, nil)
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func (h *AuthHandlers) handleAssumeLogin(ctx context.Context, w http.ResponseWriter, req *http.Request) {
|
||||
// no auth cookie, try to get get assume user token from header
|
||||
assumeToken, err := getAssumeToken(req)
|
||||
if err != nil {
|
||||
appsrv.Send(w, err.Error())
|
||||
return
|
||||
}
|
||||
token, err := doAssumeLogin(assumeToken, w, req)
|
||||
if err != nil {
|
||||
appsrv.Send(w, err.Error())
|
||||
return
|
||||
}
|
||||
_, query, _ := appsrv.FetchEnv(ctx, w, req)
|
||||
redirect := ""
|
||||
if query != nil {
|
||||
queryMap, err := query.GetMap()
|
||||
if err != nil {
|
||||
appsrv.Send(w, err.Error())
|
||||
return
|
||||
}
|
||||
for k, v := range queryMap {
|
||||
if k == "p" {
|
||||
redirect, _ = v.GetString()
|
||||
} else {
|
||||
value, _ := v.GetString()
|
||||
saveCookie(w, k, value, "", token.GetExpires(), false)
|
||||
}
|
||||
}
|
||||
}
|
||||
if !strings.HasPrefix(redirect, "/") {
|
||||
redirect = "/" + redirect
|
||||
}
|
||||
appsrv.SendRedirect(w, redirect)
|
||||
}
|
||||
@@ -85,6 +85,7 @@ func (h *AuthHandlers) AddMethods() {
|
||||
NewHP(handleOIDCJWKeys, "oidc", "keys"),
|
||||
NewHP(handleOIDCUserInfo, "oidc", "user"),
|
||||
NewHP(handleOIDCRPInitLogout, "oidc", "logout"),
|
||||
NewHP(h.handleAssumeLogin, "assume"),
|
||||
)
|
||||
h.AddByMethod(POST, nil,
|
||||
NewHP(h.initTotpSecrets, "initcredential"),
|
||||
@@ -661,31 +662,34 @@ func (h *AuthHandlers) doLogin(ctx context.Context, w http.ResponseWriter, req *
|
||||
return httperrors.NewForbiddenError("user forbidden login from web")
|
||||
}
|
||||
|
||||
saveLoginCookies(w, authToken, token, body)
|
||||
return nil
|
||||
}
|
||||
|
||||
func saveLoginCookies(w http.ResponseWriter, authToken *clientman.SAuthToken, token mcclient.TokenCredential, body jsonutils.JSONObject) {
|
||||
saveAuthCookie(w, authToken, token)
|
||||
|
||||
if len(token.GetProjectId()) > 0 {
|
||||
if body.Contains("isadmin") {
|
||||
if body != nil && body.Contains("isadmin") {
|
||||
adminVal := "false"
|
||||
if policy.PolicyManager.IsScopeCapable(token, rbacscope.ScopeSystem) {
|
||||
adminVal, _ = body.GetString("isadmin")
|
||||
}
|
||||
saveCookie(w, "isadmin", adminVal, "", token.GetExpires(), false)
|
||||
}
|
||||
if body.Contains("scope") {
|
||||
if body != nil && body.Contains("scope") {
|
||||
scopeStr, _ := body.GetString("scope")
|
||||
if !policy.PolicyManager.IsScopeCapable(token, rbacscope.TRbacScope(scopeStr)) {
|
||||
scopeStr = string(rbacscope.ScopeProject)
|
||||
}
|
||||
saveCookie(w, "scope", scopeStr, "", token.GetExpires(), false)
|
||||
}
|
||||
if body.Contains("domain") {
|
||||
if body != nil && body.Contains("domain") {
|
||||
domainStr, _ := body.GetString("domain")
|
||||
saveCookie(w, "domain", domainStr, "", token.GetExpires(), false)
|
||||
}
|
||||
saveCookie(w, "tenant", token.GetProjectId(), "", token.GetExpires(), false)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func doLogout(ctx context.Context, w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
@@ -33,11 +33,18 @@ import (
|
||||
|
||||
type SBackendServiceProxyHandler struct {
|
||||
prefix string
|
||||
|
||||
readWorker *appsrv.SWorkerManager
|
||||
writeWorker *appsrv.SWorkerManager
|
||||
}
|
||||
|
||||
func NewBackendServiceProxyHandler(prefix string) *SBackendServiceProxyHandler {
|
||||
func NewBackendServiceProxyHandler(prefix string, readWorkerCount, writeWorkerCount int) *SBackendServiceProxyHandler {
|
||||
log.Infof("NewBackendServiceProxyHandler: %s, readWorkerCount: %d, writeWorkerCount: %d", prefix, readWorkerCount, writeWorkerCount)
|
||||
return &SBackendServiceProxyHandler{
|
||||
prefix: prefix,
|
||||
|
||||
readWorker: appsrv.NewWorkerManager("apigateway-backend-api-read", readWorkerCount, appsrv.DEFAULT_BACKLOG, false),
|
||||
writeWorker: appsrv.NewWorkerManager("apigateway-backend-api-write", writeWorkerCount, appsrv.DEFAULT_BACKLOG, false),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,9 +103,9 @@ func (h *SBackendServiceProxyHandler) Bind(app *appsrv.Application) {
|
||||
}
|
||||
var worker *appsrv.SWorkerManager
|
||||
if method == "GET" || method == "HEAD" {
|
||||
worker = appsrv.NewWorkerManager("apigateway-backend-api-read", 8, appsrv.DEFAULT_BACKLOG, false)
|
||||
worker = h.readWorker
|
||||
} else {
|
||||
worker = appsrv.NewWorkerManager("apigateway-backend-api-write", 4, appsrv.DEFAULT_BACKLOG, false)
|
||||
worker = h.writeWorker
|
||||
}
|
||||
hi.SetWorkerManager(worker)
|
||||
return hi
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/appctx"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
@@ -95,10 +96,12 @@ func fetchAuthInfo(ctx context.Context, r *http.Request) (mcclient.TokenCredenti
|
||||
var err error
|
||||
authToken, err = clientman.Decode(auth)
|
||||
if err != nil {
|
||||
log.Errorf("clientman.Decode auth token fail: %v", err)
|
||||
return nil, nil, errors.Wrap(httperrors.ErrInputParameter, "clientman.Decode auth token fail")
|
||||
}
|
||||
token, err = authToken.GetToken(ctx)
|
||||
if err != nil {
|
||||
log.Errorf("authToken.GetToken fail: %v", err)
|
||||
return nil, nil, errors.Wrap(httperrors.ErrInputParameter, "authToken.GetToken fail")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,9 @@ type GatewayOptions struct {
|
||||
DisableReporting bool `default:"false" help:"Reporting data every 24 hours, report data incloud version, os, platform and usages"`
|
||||
|
||||
// 启用后端服务反向代理网关
|
||||
EnableBackendServiceProxy bool `default:"false" help:"Proxy API request to backend services"`
|
||||
EnableBackendServiceProxy bool `default:"true" help:"Proxy API request to backend services"`
|
||||
BackendProxyReadWorkerCount int `default:"8" help:"Request worker thread count, default is 8"`
|
||||
BackendProxyWriteWorkerCount int `default:"4" help:"Request worker thread count, default is 4"`
|
||||
|
||||
common_options.CommonOptions `"request_worker_count->default":"32"`
|
||||
|
||||
|
||||
@@ -17,7 +17,8 @@ package cloudevent
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
const (
|
||||
SERVICE_TYPE = apis.SERVICE_TYPE_CLOUDEVENT
|
||||
SERVICE_TYPE = apis.SERVICE_TYPE_CLOUDEVENT
|
||||
SERVICE_VERSION = ""
|
||||
|
||||
CLOUD_EVENT_SERVICE_COMPUTE = "compute"
|
||||
CLOUD_EVENT_SERVICE_UNKNOWN = "unknown"
|
||||
|
||||
@@ -312,6 +312,7 @@ type BaremetalDiskConfig struct {
|
||||
RA *bool `json:"ra,omitempty"`
|
||||
WT *bool `json:"wt,omitempty"`
|
||||
Direct *bool `json:"direct,omitempty"`
|
||||
SoftRaidIdx *int `json:"soft_raid_idx"`
|
||||
}
|
||||
|
||||
type RootDiskMatcherSizeMBRange struct {
|
||||
@@ -327,6 +328,7 @@ type BaremetalRootDiskMatcher struct {
|
||||
Device string `json:"device"`
|
||||
SizeMB int64 `json:"size_mb"`
|
||||
SizeMBRange *RootDiskMatcherSizeMBRange `json:"size_mb_range"`
|
||||
PCIPath string `json:"pci_path"`
|
||||
}
|
||||
|
||||
type ServerConfigs struct {
|
||||
|
||||
@@ -64,6 +64,11 @@ var (
|
||||
DISK_DRIVER_ADAPTECRAID,
|
||||
)
|
||||
|
||||
DISK_DRIVERS_SOFT_RAID = sets.NewString(
|
||||
DISK_DRIVER_LINUX,
|
||||
DISK_DRIVER_PCIE,
|
||||
)
|
||||
|
||||
DISK_DRIVERS = sets.NewString(
|
||||
DISK_DRIVER_LINUX,
|
||||
DISK_DRIVER_PCIE).Union(DISK_DRIVERS_RAID)
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
package version
|
||||
|
||||
// Copyright (c) Microsoft and contributors. All rights reserved.
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
// Changes may cause incorrect behavior and will be lost if the code is regenerated.
|
||||
|
||||
// Number contains the semantic version of this SDK.
|
||||
const Number = "v36.1.0"
|
||||
package compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
)
|
||||
|
||||
type BillingResourceCheckListInput struct {
|
||||
apis.VirtualResourceListInput
|
||||
|
||||
ResourceType []string `json:"resource_type"`
|
||||
}
|
||||
@@ -87,6 +87,6 @@ type CachedimageListInput struct {
|
||||
// valid cachedimage
|
||||
Valid bool `json:"valid"`
|
||||
|
||||
// enum: [public, private]
|
||||
// enum: ["public", "private"]
|
||||
CloudEnv string `json:"cloud_env"`
|
||||
}
|
||||
|
||||
@@ -368,6 +368,9 @@ func (self CloudaccountDetail) GetMetricTags() map[string]string {
|
||||
"domain_id": self.DomainId,
|
||||
"project_domain": self.ProjectDomain,
|
||||
"currency": self.Currency,
|
||||
"tenant_id": self.ProjectId,
|
||||
"tenant": self.Project,
|
||||
"status": self.Status,
|
||||
}
|
||||
return AppendMetricTags(ret, self.MetadataResourceInfo, self.ProjectizedResourceInfo)
|
||||
}
|
||||
|
||||
@@ -117,7 +117,10 @@ type DiskListInput struct {
|
||||
StorageFilterListInput
|
||||
|
||||
SnapshotPolicyFilterListInput
|
||||
ServerFilterListInput
|
||||
// 虚拟机(ID或Name)列表
|
||||
ServerId []string `json:"server_id"`
|
||||
// swagger:ignore
|
||||
Server []string `json:"server" yunion-deprecated-by:"server_id"`
|
||||
|
||||
// filter disk by whether it is being used
|
||||
Unused *bool `json:"unused"`
|
||||
@@ -166,6 +169,8 @@ type DiskListInput struct {
|
||||
|
||||
// 根据是否绑定快照策略过滤
|
||||
BindingSnapshotpolicy *bool `json:"binding_snapshotpolicy"`
|
||||
// 根据是否磁盘所在虚拟机是否绑定主机快照策略
|
||||
BindingServerSnapshotpolicy *bool `json:"binding_server_snapshotpolicy"`
|
||||
}
|
||||
|
||||
type DiskResourceInput struct {
|
||||
@@ -210,13 +215,22 @@ type SimpleGuest struct {
|
||||
Bps int `json:"bps"`
|
||||
// 计费类型
|
||||
BillingType string `json:"billing_type"`
|
||||
|
||||
// 磁盘绑定的快照策略列表
|
||||
Snapshotpolicy []SimpleSnapshotPolicy `json:"snapshotpolicy"`
|
||||
}
|
||||
|
||||
type SimpleSnapshotPolicy struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
RepeatWeekdays []int `json:"repeat_weekdays"`
|
||||
TimePoints []int `json:"time_points"`
|
||||
// 快照策略ID
|
||||
Id string `json:"id"`
|
||||
// 快照策略名称
|
||||
Name string `json:"name"`
|
||||
// 快照策略类型
|
||||
ResourceType string `json:"resource_type"`
|
||||
// 快照策略重复周期
|
||||
RepeatWeekdays []int `json:"repeat_weekdays"`
|
||||
// 快照策略时间点
|
||||
TimePoints []int `json:"time_points"`
|
||||
}
|
||||
|
||||
type DiskDetails struct {
|
||||
@@ -236,11 +250,11 @@ type DiskDetails struct {
|
||||
GuestStatus string `json:"guest_status"`
|
||||
// 所挂载虚拟机计费类型
|
||||
GuestBillingType string `json:"guest_billing_type"`
|
||||
// 磁盘所在虚拟机绑定的主机快照策略数量
|
||||
GuestSnapshotpolicyCount int `json:"guest_snapshotpolicy_count"`
|
||||
|
||||
// 自动清理时间
|
||||
AutoDeleteAt time.Time `json:"auto_delete_at"`
|
||||
// 自动快照策略状态
|
||||
SnapshotpolicyStatus string `json:"snapshotpolicy_status,allowempty"`
|
||||
|
||||
// 自动快照策略
|
||||
Snapshotpolicies []SimpleSnapshotPolicy `json:"snapshotpolicies"`
|
||||
@@ -342,7 +356,13 @@ type DiskMigrateInput struct {
|
||||
TargetStorageId string `json:"target_storage_id"`
|
||||
}
|
||||
|
||||
type DiskChagneStorageTypeInput struct {
|
||||
// 目标存储类型
|
||||
StorageType string `json:"storage_type"`
|
||||
}
|
||||
|
||||
type DiskSnapshotpolicyInput struct {
|
||||
// 快照策略ID
|
||||
SnapshotpolicyId string `json:"snapshotpolicy_id"`
|
||||
}
|
||||
|
||||
|
||||
@@ -94,6 +94,7 @@ type GuestdiskJsonDesc struct {
|
||||
IsSSD bool `json:"is_ssd"`
|
||||
NumQueues uint8 `json:"num_queues"`
|
||||
AutoReset bool `json:"auto_reset"`
|
||||
PCIPath string `json:"pci_path"`
|
||||
|
||||
// esxi
|
||||
ImageInfo struct {
|
||||
|
||||
@@ -27,3 +27,26 @@ type SImagesInGuest struct {
|
||||
RootImage SSubImage
|
||||
DataImages []SSubImage
|
||||
}
|
||||
|
||||
type SGuestScreenDumpInfo struct {
|
||||
S3AccessKey string
|
||||
S3SecretKey string
|
||||
S3Endpoint string
|
||||
S3BucketName string
|
||||
S3ObjectName string
|
||||
S3UseSSL bool
|
||||
}
|
||||
|
||||
type GuestScreenDumpListInput struct {
|
||||
Server string
|
||||
}
|
||||
|
||||
type GetDetailsGuestScreenDumpInput struct {
|
||||
ObjectName string
|
||||
}
|
||||
|
||||
type GetDetailsGuestScreenDumpOutput struct {
|
||||
GuestId string
|
||||
Name string
|
||||
ScreenDump string
|
||||
}
|
||||
|
||||
@@ -53,6 +53,8 @@ type GuestnetworkShortDesc struct {
|
||||
NetworkId string `json:"network_id"`
|
||||
// 附属IP
|
||||
SubIps string `json:"sub_ips"`
|
||||
// 网卡序号
|
||||
Index int `json:"index"`
|
||||
}
|
||||
|
||||
type GuestnetworkListInput struct {
|
||||
|
||||
@@ -134,6 +134,14 @@ type ServerListInput struct {
|
||||
|
||||
// 根据是否绑定快照策略过滤
|
||||
BindingSnapshotpolicy *bool `json:"binding_snapshotpolicy"`
|
||||
// 根据虚机关联的磁盘是否绑定快照策略过滤
|
||||
BindingDisksSnapshotpolicy *bool `json:"binding_disks_snapshotpolicy"`
|
||||
}
|
||||
|
||||
// 主机快照策略绑定/设置接口入参
|
||||
type ServerSnapshotpolicyInput struct {
|
||||
// 快照策略ID
|
||||
SnapshotpolicyId string `json:"snapshotpolicy_id"`
|
||||
}
|
||||
|
||||
func (input *ServerListInput) AfterUnmarshal() {
|
||||
@@ -183,6 +191,11 @@ type ServerDetails struct {
|
||||
// 磁盘概要
|
||||
Disks string `json:"disks"`
|
||||
|
||||
// 主机快照策略数量
|
||||
SnapshotpolicyCount int `json:"snapshotpolicy_count"`
|
||||
// 磁盘快照策略数量
|
||||
DisksSnapshotpolicyCount int `json:"disks_snapshotpolicy_count"`
|
||||
|
||||
// 磁盘详情
|
||||
DisksInfo []GuestDiskInfo `json:"disks_info"`
|
||||
// 虚拟机Ip列表
|
||||
@@ -712,6 +725,13 @@ func (input ServerDetachnetworkInput) IsForce() bool {
|
||||
return input.Force != nil && *input.Force
|
||||
}
|
||||
|
||||
type ServerSetNetworkNumQueuesInput struct {
|
||||
// 虚机网卡 mac addr
|
||||
MacAddr string `json:"mac_addr"`
|
||||
// 网卡队列数
|
||||
NumQueues int `json:"num_queues"`
|
||||
}
|
||||
|
||||
type ServerMigrateForecastInput struct {
|
||||
PreferHostId string `json:"prefer_host_id"`
|
||||
// Deprecated
|
||||
|
||||
@@ -419,6 +419,8 @@ type HostSizeAttributes struct {
|
||||
CpuMicrocode string `json:"cpu_microcode"`
|
||||
// CPU架构
|
||||
CpuArchitecture string `json:"cpu_architecture"`
|
||||
// KVM 允许单台虚机最大 vcpu 个数
|
||||
KvmCapMaxVcpu *int `json:"kvm_cap_max_vcpu"`
|
||||
|
||||
// 内存大小(单位MB)
|
||||
MemSize string `json:"mem_size"`
|
||||
@@ -579,6 +581,17 @@ type SHostPingInput struct {
|
||||
QgaRunningGuestIds []string `json:"qga_running_guests"`
|
||||
}
|
||||
|
||||
type SKmsgEntry struct {
|
||||
Level int `json:"level"`
|
||||
Seq int `json:"sql"`
|
||||
Message string `json:"message"`
|
||||
Time time.Time `json:"time"`
|
||||
}
|
||||
|
||||
type SHostReportDmesgInput struct {
|
||||
Entries []SKmsgEntry `json:"entries"`
|
||||
}
|
||||
|
||||
type HostReserveCpusInput struct {
|
||||
Cpus string
|
||||
Mems string
|
||||
|
||||
@@ -69,6 +69,9 @@ type SchedtagListInput struct {
|
||||
Type string `json:"type" yunion-deprecated-by:"resource_type"`
|
||||
|
||||
DefaultStrategy []string `json:"default_strategy"`
|
||||
|
||||
// filter by zone_id
|
||||
ZoneId []string `json:"zone_id"`
|
||||
}
|
||||
|
||||
type SchedtagDetails struct {
|
||||
|
||||
@@ -46,6 +46,8 @@ type SnapshotPolicyDetails struct {
|
||||
|
||||
BindingDiskCount int `json:"binding_disk_count"`
|
||||
BindingResourceCount int `json:"binding_resource_count"`
|
||||
// 快照数量
|
||||
SnapshotCount int `json:"snapshot_count"`
|
||||
}
|
||||
|
||||
type SSnapshotPolicyCreateInput struct {
|
||||
|
||||
@@ -133,6 +133,21 @@ const (
|
||||
STORAGE_ECLOUD_SSD = compute.STORAGE_ECLOUD_SSD // 高性能盘
|
||||
STORAGE_ECLOUD_SSDEBS = compute.STORAGE_ECLOUD_SSDEBS // 性能优化盘
|
||||
STORAGE_ECLOUD_SYSTEM = compute.STORAGE_ECLOUD_SYSTEM // 系统盘
|
||||
|
||||
STORAGE_BAIDU_SSD = compute.STORAGE_BAIDU_SSD
|
||||
STORAGE_BAIDU_PREMIUM_SSD = compute.STORAGE_BAIDU_PREMIUM_SSD
|
||||
STORAGE_BAIDU_HDD = compute.STORAGE_BAIDU_HDD
|
||||
STORAGE_BAIDU_ENHANCED_SSD_PL1 = compute.STORAGE_BAIDU_ENHANCED_SSD_PL1
|
||||
STORAGE_BAIDU_ENHANCED_SSD_PL2 = compute.STORAGE_BAIDU_ENHANCED_SSD_PL2
|
||||
STORAGE_BAIDU_ENHANCED_SSD_PL3 = compute.STORAGE_BAIDU_ENHANCED_SSD_PL3
|
||||
|
||||
// ksyun storage type
|
||||
STORAGE_KSYUN_ESSD_AUTO_PL = compute.STORAGE_KSYUN_ESSD_AUTO_PL
|
||||
STORAGE_KSYUN_SSD3_0 = compute.STORAGE_KSYUN_SSD3_0
|
||||
STORAGE_KSYUN_EHDD = compute.STORAGE_KSYUN_EHDD
|
||||
STORAGE_KSYUN_ESSD_PL1 = compute.STORAGE_KSYUN_ESSD_PL1
|
||||
STORAGE_KSYUN_ESSD_PL2 = compute.STORAGE_KSYUN_ESSD_PL2
|
||||
STORAGE_KSYUN_ESSD_PL3 = compute.STORAGE_KSYUN_ESSD_PL3
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -169,7 +184,7 @@ var (
|
||||
}
|
||||
STORAGE_TYPES = []string{STORAGE_LOCAL, STORAGE_BAREMETAL, STORAGE_SHEEPDOG,
|
||||
STORAGE_RBD, STORAGE_DOCKER, STORAGE_NAS, STORAGE_VSAN, STORAGE_NFS,
|
||||
STORAGE_PUBLIC_CLOUD, STORAGE_CLOUD_SSD, STORAGE_CLOUD_ESSD, STORAGE_CLOUD_ESSD_PL2, STORAGE_CLOUD_ESSD_PL3,
|
||||
STORAGE_PUBLIC_CLOUD, STORAGE_CLOUD_SSD, STORAGE_CLOUD_ESSD_PL0, STORAGE_CLOUD_ESSD, STORAGE_CLOUD_ESSD_PL2, STORAGE_CLOUD_ESSD_PL3,
|
||||
STORAGE_EPHEMERAL_SSD, STORAGE_CLOUD_EFFICIENCY,
|
||||
STORAGE_STANDARD_LRS, STORAGE_STANDARDSSD_LRS, STORAGE_PREMIUM_LRS,
|
||||
STORAGE_GP2_SSD, STORAGE_GP3_SSD, STORAGE_IO1_SSD, STORAGE_ST1_HDD, STORAGE_SC1_HDD, STORAGE_STANDARD_HDD,
|
||||
|
||||
@@ -586,6 +586,7 @@ type SDisk struct {
|
||||
DiskSize int `json:"disk_size"`
|
||||
// 磁盘路径
|
||||
AccessPath string `json:"access_path"`
|
||||
PCIPath string `json:"pci_path"`
|
||||
// 备份磁盘实例的存储ID
|
||||
BackupStorageId string `json:"backup_storage_id"`
|
||||
// 镜像Id
|
||||
|
||||
@@ -121,6 +121,8 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
OS_ARCH_ALL = "all"
|
||||
|
||||
OS_ARCH_X86 = "x86"
|
||||
OS_ARCH_ARM = "arm"
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ const (
|
||||
AUTH_METHOD_OIDC = "oidc"
|
||||
AUTH_METHOD_OAuth2 = "oauth2"
|
||||
AUTH_METHOD_VERIFY = "verify"
|
||||
AUTH_METHOD_ASSUME = "assume"
|
||||
|
||||
// AUTH_METHOD_ID_PASSWORD = 1
|
||||
// AUTH_METHOD_ID_TOKEN = 2
|
||||
|
||||
@@ -197,11 +197,11 @@ type UserListInput struct {
|
||||
RoleAssignmentProjectId string `json:"role_assignment_project_id"`
|
||||
|
||||
// email
|
||||
Email string `json:"email"`
|
||||
Email []string `json:"email"`
|
||||
// mobile
|
||||
Mobile string `json:"mobile"`
|
||||
Mobile []string `json:"mobile"`
|
||||
// displayname
|
||||
Displayname string `json:"displayname"`
|
||||
Displayname []string `json:"displayname"`
|
||||
|
||||
// 是否允许web控制台登录
|
||||
AllowWebConsole *bool `json:"allow_web_console"`
|
||||
|
||||
@@ -59,8 +59,10 @@ const (
|
||||
IMAGE_OS_DISTRO = "os_distribution"
|
||||
IMAGE_OS_TYPE = "os_type"
|
||||
IMAGE_OS_VERSION = "os_version"
|
||||
IMAGE_OS_LANGUAGE = "os_language"
|
||||
IMAGE_DISK_FORMAT = "disk_format"
|
||||
IMAGE_UEFI_SUPPORT = "uefi_support"
|
||||
IMAGE_BIOS_SUPPORT = "bios_support"
|
||||
IMAGE_IS_LVM_PARTITION = "is_lvm_partition"
|
||||
IMAGE_IS_READONLY = "is_readonly"
|
||||
IMAGE_PARTITION_TYPE = "partition_type"
|
||||
|
||||
@@ -383,6 +383,14 @@ type OpsLogListInput struct {
|
||||
Until time.Time `json:"until"`
|
||||
}
|
||||
|
||||
type HostDmesgLogListInput struct {
|
||||
OpsLogListInput
|
||||
|
||||
LogLevels []string `json:"log_levels"`
|
||||
|
||||
ShowDmesgLog bool `json:"show_dmesg_log"`
|
||||
}
|
||||
|
||||
type IdNameDetails struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
|
||||
@@ -56,6 +56,8 @@ type MetadataBaseFilterInput struct {
|
||||
|
||||
// 按key模糊匹配
|
||||
KeyLike string `json:"key_like"`
|
||||
// 按value模糊匹配
|
||||
ValueLike string `json:"value_like"`
|
||||
|
||||
// 按Key过滤
|
||||
Key []string `json:"key"`
|
||||
|
||||
@@ -238,3 +238,13 @@ func init() {
|
||||
return &AlertSetting{}
|
||||
})
|
||||
}
|
||||
|
||||
type EvaluatorType string
|
||||
|
||||
const (
|
||||
EvaluatorTypeGT EvaluatorType = "gt"
|
||||
EvaluatorTypeLT EvaluatorType = "lt"
|
||||
EvaluatorTypeEQ EvaluatorType = "eq"
|
||||
EvaluatorTypeWithinRange EvaluatorType = "within_range"
|
||||
EvaluatorTypeOutsideRange EvaluatorType = "outside_range"
|
||||
)
|
||||
|
||||
@@ -33,13 +33,14 @@ type AlertRecordListInput struct {
|
||||
apis.EnabledResourceBaseListInput
|
||||
apis.StatusStandaloneResourceListInput
|
||||
|
||||
AlertId string `json:"alert_id"`
|
||||
Level string `json:"level"`
|
||||
State string `json:"state"`
|
||||
ResType string `json:"res_type"`
|
||||
Alerting bool `json:"alerting"`
|
||||
ResName string `json:"res_name"`
|
||||
ResId string `json:"res_id"`
|
||||
AlertId string `json:"alert_id"`
|
||||
AlertName string `json:"alert_name"`
|
||||
Level string `json:"level"`
|
||||
State string `json:"state"`
|
||||
ResType string `json:"res_type"`
|
||||
Alerting bool `json:"alerting"`
|
||||
ResName string `json:"res_name"`
|
||||
ResId string `json:"res_id"`
|
||||
}
|
||||
|
||||
type AlertRecordDetails struct {
|
||||
@@ -77,10 +78,12 @@ type AlertRecordRule struct {
|
||||
// 比较运算符, 比如: >, <, >=, <=
|
||||
Comparator string `json:"comparator"`
|
||||
// 报警阀值
|
||||
Threshold string `json:"threshold"`
|
||||
Period string `json:"period"`
|
||||
AlertDuration int64 `json:"alert_duration"`
|
||||
ConditionType string `json:"condition_type"`
|
||||
Threshold string `json:"threshold"`
|
||||
ThresholdRange []float64 `json:"threshold_range"`
|
||||
Unit string `json:"unit"`
|
||||
Period string `json:"period"`
|
||||
AlertDuration int64 `json:"alert_duration"`
|
||||
ConditionType string `json:"condition_type"`
|
||||
// 静默期
|
||||
SilentPeriod string `json:"silent_period"`
|
||||
Reducer string `json:"reducer"`
|
||||
|
||||
@@ -34,9 +34,6 @@ const (
|
||||
|
||||
CommonAlertDefaultRecipient = "commonalert-default"
|
||||
|
||||
//metirc fields 之间的运算
|
||||
CommonAlertFieldOpt_Division = "/"
|
||||
|
||||
DEFAULT_SEND_NOTIFY_CHANNEL = "users"
|
||||
|
||||
METRIC_QUERY_TYPE_NO_DATA = "nodata_query"
|
||||
@@ -47,6 +44,13 @@ const (
|
||||
CommonAlertLevelFatal = "fatal"
|
||||
)
|
||||
|
||||
type CommonAlertFieldOpt string
|
||||
|
||||
const (
|
||||
//metirc fields 之间的运算
|
||||
CommonAlertFieldOptDivision CommonAlertFieldOpt = "/"
|
||||
)
|
||||
|
||||
var CommonAlertLevels = []string{CommonAlertLevelNormal, CommonAlertLevelImportant, CommonAlertLevelFatal}
|
||||
|
||||
type CommonAlertCreateBaseInput struct {
|
||||
@@ -96,13 +100,15 @@ type CommonAlertQuery struct {
|
||||
*AlertQuery
|
||||
// metric points'value的运算方式
|
||||
Reduce string `json:"reduce"`
|
||||
// 比较运算符, 比如: >, <, >=, <=
|
||||
// 比较运算符, 比如: >, <, >=, <=, within_range, outside_range
|
||||
Comparator string `json:"comparator"`
|
||||
// 报警阀值
|
||||
// 报警阀值 (用于 gt, lt, eq)
|
||||
Threshold float64 `json:"threshold"`
|
||||
//field yunsuan
|
||||
FieldOpt string `json:"field_opt"`
|
||||
ConditionType string `json:"condition_type"`
|
||||
// 范围参数 (用于 within_range, outside_range)
|
||||
ThresholdRange []float64 `json:"threshold_range"`
|
||||
// field 运算
|
||||
FieldOpt CommonAlertFieldOpt `json:"field_opt"`
|
||||
ConditionType string `json:"condition_type"`
|
||||
// Operator should be chosen from 'and | or'
|
||||
Operator string `json:"operator"`
|
||||
}
|
||||
@@ -161,12 +167,12 @@ type CommonAlertDetails struct {
|
||||
}
|
||||
|
||||
type CommonAlertMetricDetails struct {
|
||||
Operator string `json:"operator"`
|
||||
Comparator string `json:"comparator"`
|
||||
Threshold float64 `json:"threshold"`
|
||||
WithinRange []float64 `json:"within_range"`
|
||||
ConditionType string `json:"condition_type"`
|
||||
ThresholdStr string `json:"threshold_str"`
|
||||
Operator string `json:"operator"`
|
||||
Comparator string `json:"comparator"`
|
||||
Threshold float64 `json:"threshold"`
|
||||
ThresholdRange []float64 `json:"threshold_range"`
|
||||
ConditionType string `json:"condition_type"`
|
||||
ThresholdStr string `json:"threshold_str"`
|
||||
// metric points'value的运算方式
|
||||
Reduce string `json:"reduce"`
|
||||
DB string `json:"db"`
|
||||
|
||||
@@ -168,15 +168,15 @@ const (
|
||||
)
|
||||
|
||||
func GetNodeAlertEvaluator(comparator string, threshold float64) Condition {
|
||||
typ := ConditionGreaterThan
|
||||
typ := EvaluatorType(ConditionGreaterThan)
|
||||
switch comparator {
|
||||
case ">=", ">":
|
||||
typ = ConditionGreaterThan
|
||||
typ = EvaluatorType(ConditionGreaterThan)
|
||||
case "<=", "<":
|
||||
typ = ConditionLessThan
|
||||
typ = EvaluatorType(ConditionLessThan)
|
||||
}
|
||||
return Condition{
|
||||
Type: typ,
|
||||
Type: string(typ),
|
||||
Params: []float64{threshold},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,6 +162,7 @@ type SendParams struct {
|
||||
Header jsonutils.JSONObject
|
||||
Body jsonutils.JSONObject
|
||||
MsgKey string
|
||||
SecretKey string `json:"secret_key"`
|
||||
DomainId string
|
||||
RemoteTemplateParam SRemoteTemplateParam
|
||||
GroupKey string
|
||||
|
||||
@@ -22,51 +22,87 @@ import (
|
||||
var (
|
||||
Event SNotifyEvent
|
||||
|
||||
ActionCreate SAction = "create"
|
||||
ActionDelete SAction = "delete"
|
||||
ActionPendingDelete SAction = "pending_delete"
|
||||
ActionUpdate SAction = "update"
|
||||
ActionRebuildRoot SAction = "rebuild_root"
|
||||
ActionResetPassword SAction = "reset_password"
|
||||
ActionChangeConfig SAction = "change_config"
|
||||
ActionResize SAction = "resize"
|
||||
// 创建
|
||||
ActionCreate SAction = "create"
|
||||
// 删除
|
||||
ActionDelete SAction = "delete"
|
||||
// 放入回收站
|
||||
ActionPendingDelete SAction = "pending_delete"
|
||||
// 更新
|
||||
ActionUpdate SAction = "update"
|
||||
// 重装系统
|
||||
ActionRebuildRoot SAction = "rebuild_root"
|
||||
// 重置密码
|
||||
ActionResetPassword SAction = "reset_password"
|
||||
// 配置变更
|
||||
ActionChangeConfig SAction = "change_config"
|
||||
// 扩容
|
||||
ActionResize SAction = "resize"
|
||||
// 到期释放
|
||||
ActionExpiredRelease SAction = "expired_release"
|
||||
ActionExecute SAction = "execute"
|
||||
ActionChangeIpaddr SAction = "change_ipaddr"
|
||||
ActionSyncStatus SAction = "sync_status"
|
||||
ActionCleanData SAction = "clean_data"
|
||||
ActionMigrate SAction = "migrate"
|
||||
// 执行,例如自动快照策略执行创建快照、弹性伸缩策略执行扩容、定时任务执行等
|
||||
ActionExecute SAction = "execute"
|
||||
// IP变更
|
||||
ActionChangeIpaddr SAction = "change_ipaddr"
|
||||
// 同步状态
|
||||
ActionSyncStatus SAction = "sync_status"
|
||||
// 清理数据
|
||||
ActionCleanData SAction = "clean_data"
|
||||
// 迁移
|
||||
ActionMigrate SAction = "migrate"
|
||||
|
||||
// 添加备份服务器
|
||||
ActionCreateBackupServer SAction = "add_backup_server"
|
||||
ActionDelBackupServer SAction = "delete_backup_server"
|
||||
// 删除备份服务器
|
||||
ActionDelBackupServer SAction = "delete_backup_server"
|
||||
|
||||
ActionSyncCreate SAction = "sync_create"
|
||||
ActionSyncUpdate SAction = "sync_update"
|
||||
ActionSyncDelete SAction = "sync_delete"
|
||||
// 同步新建
|
||||
ActionSyncCreate SAction = "sync_create"
|
||||
// 同步更新
|
||||
ActionSyncUpdate SAction = "sync_update"
|
||||
// 同步删除
|
||||
ActionSyncDelete SAction = "sync_delete"
|
||||
// 同步账号状态
|
||||
ActionSyncAccountStatus SAction = "sync_account_status"
|
||||
|
||||
ActionOffline SAction = "offline"
|
||||
ActionSystemPanic SAction = "panic"
|
||||
// 下线
|
||||
ActionOffline SAction = "offline"
|
||||
// 系统崩溃
|
||||
ActionSystemPanic SAction = "panic"
|
||||
// 系统异常
|
||||
ActionSystemException SAction = "exception"
|
||||
|
||||
ActionChecksumTest SAction = "checksum_test"
|
||||
|
||||
// 锁定,例如用户锁定
|
||||
ActionLock SAction = "lock"
|
||||
|
||||
ActionExceedCount SAction = "exceed_count"
|
||||
ActionPasswordExpireSoon SAction = "password_expire_soon"
|
||||
ActionWorkerBlock SAction = "woker_block"
|
||||
ActionNetOutOfSync SAction = "net_out_of_sync"
|
||||
ActionMysqlOutOfSync SAction = "mysql_out_of_sync"
|
||||
ActionServiceAbnormal SAction = "service_abnormal"
|
||||
ActionServerPanicked SAction = "server_panicked"
|
||||
ActionAttach SAction = "attach"
|
||||
ActionDetach SAction = "detach"
|
||||
// 超出数量
|
||||
ActionExceedCount SAction = "exceed_count"
|
||||
// 密码即将过期
|
||||
ActionPasswordExpireSoon SAction = "password_expire_soon"
|
||||
// 一致性检查
|
||||
ActionChecksumTest SAction = "checksum_test"
|
||||
// 任务队列阻塞
|
||||
ActionWorkerBlock SAction = "woker_block"
|
||||
// 网络同步失败
|
||||
ActionNetOutOfSync SAction = "net_out_of_sync"
|
||||
// MySQL同步失败
|
||||
ActionMysqlOutOfSync SAction = "mysql_out_of_sync"
|
||||
// 服务异常
|
||||
ActionServiceAbnormal SAction = "service_abnormal"
|
||||
// 服务器崩溃
|
||||
ActionServerPanicked SAction = "server_panicked"
|
||||
// 挂载
|
||||
ActionAttach SAction = "attach"
|
||||
// 卸载
|
||||
ActionDetach SAction = "detach"
|
||||
// 透传设备创建
|
||||
ActionIsolatedDeviceCreate SAction = "isolated_device_create"
|
||||
// 透传设备更新
|
||||
ActionIsolatedDeviceUpdate SAction = "isolated_device_update"
|
||||
// 透传设备删除
|
||||
ActionIsolatedDeviceDelete SAction = "isolated_device_delete"
|
||||
ActionStatusChanged SAction = "status_changed"
|
||||
ActionRunTask SAction = "run_task"
|
||||
// 状态变更
|
||||
ActionStatusChanged SAction = "status_changed"
|
||||
// 运行任务
|
||||
ActionRunTask SAction = "run_task"
|
||||
|
||||
ResultFailed SResult = "failed"
|
||||
ResultSucceed SResult = "succeed"
|
||||
|
||||
@@ -19,6 +19,8 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/pkg/tristate"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
)
|
||||
|
||||
@@ -65,6 +67,9 @@ var (
|
||||
func ParseInternationalMobile(mobile string) SInternationalMobile {
|
||||
matchs := pareser.FindStringSubmatch(mobile)
|
||||
if len(matchs) == 0 {
|
||||
if len(mobile) == 0 {
|
||||
return SInternationalMobile{}
|
||||
}
|
||||
return SInternationalMobile{
|
||||
AreaCode: defaultAreaCode,
|
||||
Mobile: mobile,
|
||||
@@ -85,7 +90,7 @@ func (im *SInternationalMobile) AcceptExtMobile() {
|
||||
// 对传入的手机号去除地区编号
|
||||
func moveAreaCode(mobile string) string {
|
||||
// 所有地区编号
|
||||
allArea := `283|282|281|280|269|268|267|266|265|264|263|262|261|260|259|258|257|256|255|254|253|252|251|250|249|248|247|246|245|244|243|242|241|240|239|238|237|236|235|234|233|232|231|230|229|228|227|226|225|224|223|222|221|220|219|218|217|216|215|214|213|212|211|210|98|95|94|93|92|91|90|86|84|82|81|66|65|64|63|62|61|60|58|57|56|55|54|53|52|51|49|48|47|46|45|44|43|41|40|39|36|34|33|32|31|30|27|20|7|1`
|
||||
allArea := `852|283|282|281|280|269|268|267|266|265|264|263|262|261|260|259|258|257|256|255|254|253|252|251|250|249|248|247|246|245|244|243|242|241|240|239|238|237|236|235|234|233|232|231|230|229|228|227|226|225|224|223|222|221|220|219|218|217|216|215|214|213|212|211|210|98|95|94|93|92|91|90|86|84|82|81|66|65|64|63|62|61|60|58|57|56|55|54|53|52|51|49|48|47|46|45|44|43|41|40|39|36|34|33|32|31|30|27|20|7|1`
|
||||
temp := strings.Split(allArea, "|")
|
||||
for _, area := range temp {
|
||||
if strings.HasPrefix(mobile, "+"+area) {
|
||||
@@ -111,6 +116,9 @@ func moveExtStr(mobile string) string {
|
||||
}
|
||||
|
||||
func (im SInternationalMobile) String() string {
|
||||
if len(im.Mobile) == 0 {
|
||||
return ""
|
||||
}
|
||||
if im.AreaCode == "" {
|
||||
return im.Mobile
|
||||
}
|
||||
@@ -159,6 +167,17 @@ type ReceiverUpdateInput struct {
|
||||
// example: example@gmail.com
|
||||
Email string `json:"email"`
|
||||
|
||||
// swagger:ignore
|
||||
EnabledEmail tristate.TriState `json:"enabled_email"`
|
||||
// swagger:ignore
|
||||
VerifiedEmail tristate.TriState `json:"verified_email"`
|
||||
// swagger:ignore
|
||||
EnabledMobile tristate.TriState `json:"enabled_mobile"`
|
||||
// swagger:ignore
|
||||
VerifiedMobile tristate.TriState `json:"verified_mobile"`
|
||||
// swagger:ignore
|
||||
Mobile string `json:"mobile"`
|
||||
|
||||
InternationalMobile SInternationalMobile `json:"international_mobile"`
|
||||
|
||||
// description: enabled contacts for user
|
||||
|
||||
@@ -23,15 +23,15 @@ func TestMobileExt(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
SInternationalMobile{
|
||||
"+8612345678901",
|
||||
"+86",
|
||||
Mobile: "+8612345678901",
|
||||
AreaCode: "+86",
|
||||
},
|
||||
"12345678901",
|
||||
},
|
||||
{
|
||||
SInternationalMobile{
|
||||
"+8612345678901;ext=2",
|
||||
"+86",
|
||||
Mobile: "+8612345678901;ext=2",
|
||||
AreaCode: "+86",
|
||||
},
|
||||
"12345678901",
|
||||
},
|
||||
@@ -56,6 +56,20 @@ func TestMobileExt(t *testing.T) {
|
||||
},
|
||||
"12345678901",
|
||||
},
|
||||
{
|
||||
SInternationalMobile{
|
||||
"13811111111",
|
||||
"",
|
||||
},
|
||||
"13811111111",
|
||||
},
|
||||
{
|
||||
SInternationalMobile{
|
||||
"+85213811111111",
|
||||
"",
|
||||
},
|
||||
"13811111111",
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
|
||||
@@ -21,6 +21,10 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
)
|
||||
|
||||
const (
|
||||
WEBHOOK_SIGNATURE_HEADER = "X-Auth-Token"
|
||||
)
|
||||
|
||||
type RobotCreateInput struct {
|
||||
apis.SharableVirtualResourceCreateInput
|
||||
apis.EnabledBaseResourceCreateInput
|
||||
@@ -37,6 +41,7 @@ type RobotCreateInput struct {
|
||||
Header jsonutils.JSONObject `json:"header"`
|
||||
Body jsonutils.JSONObject `json:"body"`
|
||||
MsgKey string `json:"msg_key"`
|
||||
SecretKey string `json:"secret_key"`
|
||||
UseTemplate tristate.TriState `json:"use_template"`
|
||||
}
|
||||
|
||||
@@ -63,8 +68,9 @@ type RobotUpdateInput struct {
|
||||
Address string `json:"address"`
|
||||
// description: Language preference
|
||||
// example: en
|
||||
Lang string `json:"lang"`
|
||||
Header jsonutils.JSONObject `json:"header"`
|
||||
Body jsonutils.JSONObject `json:"body"`
|
||||
MsgKey string `json:"msg_key"`
|
||||
Lang string `json:"lang"`
|
||||
Header jsonutils.JSONObject `json:"header"`
|
||||
Body jsonutils.JSONObject `json:"body"`
|
||||
MsgKey string `json:"msg_key"`
|
||||
SecretKey string `json:"secret_key"`
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ type ServerConfig struct {
|
||||
Name string `json:"name"`
|
||||
GuestStatus string `json:"guest_status"`
|
||||
Cdrom string `json:"cdrom"`
|
||||
Bios string `json:"bios"`
|
||||
|
||||
// owner project id
|
||||
Project string `json:"project_id"`
|
||||
|
||||
@@ -38,4 +38,8 @@ const (
|
||||
CLOUDPODS = "cloudpods"
|
||||
PROXMOX = "proxmox"
|
||||
VOLC_ENGINE = "volcengine"
|
||||
BAIDU = "baidu"
|
||||
SANGFOR = "sangfor"
|
||||
CNWARE = "cnware"
|
||||
KSYUN = "ksyun"
|
||||
)
|
||||
|
||||
@@ -17,7 +17,8 @@ package yunionconf
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
const (
|
||||
SERVICE_TYPE = apis.SERVICE_TYPE_YUNIONCONF
|
||||
SERVICE_TYPE = apis.SERVICE_TYPE_YUNIONCONF
|
||||
SERVICE_VERSION = ""
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
31
pkg/apis/yunionconf/tags.go
Normal file
31
pkg/apis/yunionconf/tags.go
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package yunionconf
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
type TagListInput struct {
|
||||
apis.InfrasResourceBaseListInput
|
||||
}
|
||||
|
||||
type TagDetails struct {
|
||||
apis.InfrasResourceBaseDetails
|
||||
}
|
||||
|
||||
type TagCreateInput struct {
|
||||
apis.InfrasResourceBaseCreateInput
|
||||
|
||||
Values []string `json:"values"`
|
||||
}
|
||||
@@ -631,9 +631,10 @@ func (app *Application) listenAndServeInternal(s *http.Server, certFile, keyFile
|
||||
type TContentType string
|
||||
|
||||
const (
|
||||
ContentTypeJson = TContentType("Json")
|
||||
ContentTypeForm = TContentType("Form")
|
||||
ContentTypeUnknown = TContentType("Unknown")
|
||||
ContentTypeJson = TContentType("Json")
|
||||
ContentTypeForm = TContentType("Form")
|
||||
ContentTypeOctetStream = TContentType("OctetStream")
|
||||
ContentTypeUnknown = TContentType("Unknown")
|
||||
)
|
||||
|
||||
func getContentType(r *http.Request) TContentType {
|
||||
@@ -649,6 +650,7 @@ func getContentType(r *http.Request) TContentType {
|
||||
for k, v := range map[string]TContentType{
|
||||
"application/json": ContentTypeJson,
|
||||
"application/x-www-form-urlencoded": ContentTypeForm,
|
||||
"application/octet-stream": ContentTypeOctetStream,
|
||||
} {
|
||||
if strings.HasPrefix(contType, k) {
|
||||
return v
|
||||
@@ -664,7 +666,6 @@ func FetchEnv(ctx context.Context, w http.ResponseWriter, r *http.Request) (para
|
||||
if err != nil {
|
||||
log.Errorf("Parse query string %s failed: %v", r.URL.RawQuery, err)
|
||||
}
|
||||
//var body jsonutils.JSONObject = nil
|
||||
if r.Method == "PUT" || r.Method == "POST" || r.Method == "DELETE" || r.Method == "PATCH" {
|
||||
switch getContentType(r) {
|
||||
case ContentTypeJson:
|
||||
@@ -683,6 +684,7 @@ func FetchEnv(ctx context.Context, w http.ResponseWriter, r *http.Request) (para
|
||||
if err != nil {
|
||||
log.Warningf("Parse query string %s failed: %v", r.PostForm.Encode(), err)
|
||||
}
|
||||
case ContentTypeOctetStream:
|
||||
default:
|
||||
log.Warningf("%s invalid contentType with header %v", r.URL.String(), r.Header)
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ func (job *SStatusProbeJob) Name() string {
|
||||
|
||||
func (job *SStatusProbeJob) Do(ctx context.Context, now time.Time) error {
|
||||
if job.baremetal.IsHypervisorHost() {
|
||||
log.Infof("baremetal %q is host, skipping status probe", job.baremetal.GetName())
|
||||
log.Debugf("baremetal %q is host, skipping status probe", job.baremetal.GetName())
|
||||
return nil
|
||||
}
|
||||
bStatus := job.baremetal.GetStatus()
|
||||
|
||||
@@ -56,7 +56,9 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/baremetal/utils/disktool"
|
||||
"yunion.io/x/onecloud/pkg/baremetal/utils/grub"
|
||||
"yunion.io/x/onecloud/pkg/baremetal/utils/ipmitool"
|
||||
raid2 "yunion.io/x/onecloud/pkg/baremetal/utils/raid"
|
||||
raiddrivers "yunion.io/x/onecloud/pkg/baremetal/utils/raid/drivers"
|
||||
"yunion.io/x/onecloud/pkg/baremetal/utils/raid/mdadm"
|
||||
"yunion.io/x/onecloud/pkg/baremetal/utils/uefi"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/types"
|
||||
"yunion.io/x/onecloud/pkg/compute/baremetal"
|
||||
@@ -826,7 +828,7 @@ func (b *SBaremetalInstance) ServerLoadDesc(ctx context.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
func PowerStatusToBaremetalStatus(status string) string {
|
||||
func PowerStatusToBaremetalStatus(status types.PowerStatus) string {
|
||||
switch status {
|
||||
case types.POWER_STATUS_ON:
|
||||
return baremetalstatus.RUNNING
|
||||
@@ -836,7 +838,7 @@ func PowerStatusToBaremetalStatus(status string) string {
|
||||
return baremetalstatus.UNKNOWN
|
||||
}
|
||||
|
||||
func PowerStatusToServerStatus(bm *SBaremetalInstance, status string) string {
|
||||
func PowerStatusToServerStatus(bm *SBaremetalInstance, status types.PowerStatus) string {
|
||||
switch status {
|
||||
case types.POWER_STATUS_ON:
|
||||
if conf, _ := bm.GetSSHConfig(); conf == nil {
|
||||
@@ -890,7 +892,7 @@ func (b *SBaremetalInstance) DelayedSyncStatus(ctx context.Context, data jsonuti
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (b *SBaremetalInstance) SyncAllStatus(ctx context.Context, status string) {
|
||||
func (b *SBaremetalInstance) SyncAllStatus(ctx context.Context, status types.PowerStatus) {
|
||||
var err error
|
||||
if status == "" {
|
||||
status, err = b.GetPowerStatus()
|
||||
@@ -898,24 +900,26 @@ func (b *SBaremetalInstance) SyncAllStatus(ctx context.Context, status string) {
|
||||
log.Errorf("Get power status error: %v", err)
|
||||
}
|
||||
}
|
||||
b.SyncStatus(ctx, PowerStatusToBaremetalStatus(status), "")
|
||||
b.SyncServerStatus(PowerStatusToServerStatus(b, status))
|
||||
b.SyncStatus(ctx, PowerStatusToBaremetalStatus(status), "SyncAllStatus by baremetal-agent")
|
||||
b.SyncServerStatus(status)
|
||||
}
|
||||
|
||||
func (b *SBaremetalInstance) SyncServerStatus(status string) {
|
||||
func (b *SBaremetalInstance) SyncServerStatus(powerStatus types.PowerStatus) {
|
||||
if b.GetServerId() == "" {
|
||||
return
|
||||
}
|
||||
if status == "" {
|
||||
status := PowerStatusToServerStatus(b, powerStatus)
|
||||
if powerStatus == "" {
|
||||
powerStatus, err := b.GetPowerStatus()
|
||||
if err != nil {
|
||||
log.Errorf("Get power status error: %v", err)
|
||||
}
|
||||
status = PowerStatusToServerStatus(b, powerStatus)
|
||||
}
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(status), "status")
|
||||
_, err := modules.Servers.PerformAction(b.GetClientSession(), b.GetServerId(), "status", params)
|
||||
params := &apis.PerformStatusInput{}
|
||||
params.Status = status
|
||||
params.PowerStates = string(powerStatus)
|
||||
_, err := modules.Servers.PerformAction(b.GetClientSession(), b.GetServerId(), "status", jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
log.Errorf("Update server %s status %s error: %v", b.GetServerName(), status, err)
|
||||
return
|
||||
@@ -1311,10 +1315,17 @@ func (b *SBaremetalInstance) GetTask() tasks.ITask {
|
||||
}
|
||||
|
||||
func (b *SBaremetalInstance) SetTask(task tasks.ITask) {
|
||||
// hack: clear exist tasks if task is server destroy task
|
||||
if task.GetName() == tasks.BAREMETAL_SERVER_DESTROY_TASK {
|
||||
log.Infof("clear tasks of baremetal %s before executing %s", b.GetName(), task.GetName())
|
||||
b.taskQueue.ClearTasks()
|
||||
}
|
||||
b.taskQueue.AppendTask(task)
|
||||
if reflect.DeepEqual(task, b.taskQueue.GetTask()) {
|
||||
log.Infof("Set task equal, ExecuteTask %s", task.GetName())
|
||||
log.Infof("Execute task %s of baremetal %s", task.GetName(), b.GetName())
|
||||
tasks.ExecuteTask(task, nil)
|
||||
} else {
|
||||
log.Warningf("Append task %s of baremetal %s before executing %s", task.GetName(), b.GetName(), b.taskQueue.DebugString())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1856,7 +1867,7 @@ func (b *SBaremetalInstance) DoDiskBoot() error {
|
||||
}
|
||||
*/
|
||||
|
||||
func (b *SBaremetalInstance) GetPowerStatus() (string, error) {
|
||||
func (b *SBaremetalInstance) GetPowerStatus() (types.PowerStatus, error) {
|
||||
status, err := b.getPowerStatus()
|
||||
if err != nil {
|
||||
if errors.Cause(err) != types.ErrIPMIToolNull {
|
||||
@@ -1868,7 +1879,7 @@ func (b *SBaremetalInstance) GetPowerStatus() (string, error) {
|
||||
return status, nil
|
||||
}
|
||||
|
||||
func (b *SBaremetalInstance) getPowerStatus() (string, error) {
|
||||
func (b *SBaremetalInstance) getPowerStatus() (types.PowerStatus, error) {
|
||||
ipmiCli := b.GetIPMITool()
|
||||
if ipmiCli == nil {
|
||||
if cli, err := b.GetHostSSHClient(); err == nil {
|
||||
@@ -1886,7 +1897,11 @@ func (b *SBaremetalInstance) getPowerStatus() (string, error) {
|
||||
}
|
||||
return "", errors.Wrapf(types.ErrIPMIToolNull, "Baremetal %s", b.GetId())
|
||||
}
|
||||
return ipmitool.GetChassisPowerStatus(ipmiCli)
|
||||
cps, err := ipmitool.GetChassisPowerStatus(ipmiCli)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "ipmitool.GetChassisPowerStatus")
|
||||
}
|
||||
return types.PowerStatus(cps), nil
|
||||
}
|
||||
|
||||
func (b *SBaremetalInstance) DoPowerShutdown(soft bool) error {
|
||||
@@ -2582,6 +2597,25 @@ func (s *SBaremetalServer) GetMetadata() (*jsonutils.JSONDict, error) {
|
||||
}
|
||||
|
||||
func (s *SBaremetalServer) GetRootDiskMatcher() (*api.BaremetalRootDiskMatcher, error) {
|
||||
matcher, err := s.getRootDiskMatcher()
|
||||
if err != nil && errors.Cause(err) != errors.ErrNotFound {
|
||||
return nil, errors.Wrap(err, "getRootDiskMatcher")
|
||||
}
|
||||
if matcher == nil {
|
||||
matcher = &api.BaremetalRootDiskMatcher{}
|
||||
}
|
||||
rootDiskObj, err := s.GetRootDiskObj()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GetRootDiskObj")
|
||||
}
|
||||
pciPath, _ := rootDiskObj.GetString("pci_path")
|
||||
if pciPath != "" {
|
||||
matcher.PCIPath = pciPath
|
||||
}
|
||||
return matcher, nil
|
||||
}
|
||||
|
||||
func (s *SBaremetalServer) getRootDiskMatcher() (*api.BaremetalRootDiskMatcher, error) {
|
||||
metadata, err := s.GetMetadata()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get metadata")
|
||||
@@ -2619,6 +2653,14 @@ func (s *SBaremetalServer) GetDiskConfig() ([]*api.BaremetalDiskConfig, error) {
|
||||
return baremetal.GetLayoutRaidConfig(layouts), nil
|
||||
}
|
||||
|
||||
func (s *SBaremetalServer) GetRootDiskObj() (*jsonutils.JSONDict, error) {
|
||||
disks, _ := s.desc.GetArray("disks")
|
||||
if len(disks) == 0 {
|
||||
return nil, errors.Error("Empty disks in desc")
|
||||
}
|
||||
return disks[0].(*jsonutils.JSONDict), nil
|
||||
}
|
||||
|
||||
func (s *SBaremetalServer) NewConfigedSSHPartitionTool(term *ssh.Client) (*disktool.SSHPartitionTool, error) {
|
||||
raid, nonRaid, pcie, err := detect_storages.DetectStorageInfo(term, false)
|
||||
if err != nil {
|
||||
@@ -2637,15 +2679,32 @@ func (s *SBaremetalServer) NewConfigedSSHPartitionTool(term *ssh.Client) (*diskt
|
||||
return nil, fmt.Errorf("CalculateLayout: %v", err)
|
||||
}
|
||||
|
||||
log.Errorf("NewConfigedSSHPartitionTool layouts: %s", jsonutils.Marshal(layouts))
|
||||
diskConfs := baremetal.GroupLayoutResultsByDriverAdapter(layouts)
|
||||
for _, dConf := range diskConfs {
|
||||
driver := dConf.Driver
|
||||
adapter := dConf.Adapter
|
||||
isSoftRaid := baremetal.DISK_DRIVERS_SOFT_RAID.Has(driver)
|
||||
|
||||
raidDrv := raiddrivers.GetDriver(driver, term)
|
||||
if raidDrv != nil {
|
||||
if err := raidDrv.ParsePhyDevs(); err != nil {
|
||||
return nil, fmt.Errorf("RaidDriver %s parse physical devices: %v", raidDrv.GetName(), err)
|
||||
}
|
||||
if isSoftRaid {
|
||||
devs := make([]*baremetal.BaremetalStorage, 0)
|
||||
for _, layout := range layouts {
|
||||
if len(layout.Disks) > 0 && layout.Disks[0].Driver == driver && layout.Disks[0].Adapter == dConf.Adapter {
|
||||
devs = append(devs, layout.Disks...)
|
||||
}
|
||||
}
|
||||
|
||||
log.Infof("SetDevicesForAdapter %v", jsonutils.Marshal(devs))
|
||||
if mdadmDrver, ok := raidDrv.(raid2.IRaidDeviceSetter); ok {
|
||||
mdadmDrver.SetDevicesForAdapter(dConf.Adapter, devs)
|
||||
}
|
||||
}
|
||||
|
||||
if err := raiddrivers.PostBuildRaid(raidDrv, adapter); err != nil {
|
||||
return nil, fmt.Errorf("Build %s raid failed: %v", raidDrv.GetName(), err)
|
||||
}
|
||||
@@ -2681,9 +2740,8 @@ func (s *SBaremetalServer) DoDiskConfig(term *ssh.Client) (*disktool.SSHPartitio
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("CalculateLayout: %v", err)
|
||||
}
|
||||
log.Errorf("===layouts: %s", jsonutils.Marshal(layouts).PrettyString())
|
||||
diskConfs := baremetal.GroupLayoutResultsByDriverAdapter(layouts)
|
||||
log.Errorf("===diskConfs: %s", jsonutils.Marshal(diskConfs).PrettyString())
|
||||
log.Errorf("%s layouts: %s, diskConfs: %s", s.GetName(), jsonutils.Marshal(layouts).PrettyString(), jsonutils.Marshal(diskConfs).PrettyString())
|
||||
for _, dConf := range diskConfs {
|
||||
driver := dConf.Driver
|
||||
raidDrv := raiddrivers.GetDriver(driver, term)
|
||||
@@ -2698,11 +2756,27 @@ func (s *SBaremetalServer) DoDiskConfig(term *ssh.Client) (*disktool.SSHPartitio
|
||||
for _, dConf := range diskConfs {
|
||||
driver := dConf.Driver
|
||||
adapter := dConf.Adapter
|
||||
isSoftRaid := baremetal.DISK_DRIVERS_SOFT_RAID.Has(driver)
|
||||
|
||||
raidDrv := raiddrivers.GetDriver(driver, term)
|
||||
if raidDrv != nil {
|
||||
if err := raidDrv.ParsePhyDevs(); err != nil {
|
||||
return nil, fmt.Errorf("RaidDriver %s parse physical devices: %v", raidDrv.GetName(), err)
|
||||
}
|
||||
if isSoftRaid {
|
||||
devs := make([]*baremetal.BaremetalStorage, 0)
|
||||
for _, layout := range layouts {
|
||||
if len(layout.Disks) > 0 && layout.Disks[0].Driver == driver && layout.Disks[0].Adapter == dConf.Adapter {
|
||||
devs = append(devs, layout.Disks...)
|
||||
}
|
||||
}
|
||||
|
||||
log.Infof("SetDevicesForAdapter %v", jsonutils.Marshal(devs))
|
||||
if mdadmDriver, ok := raidDrv.(raid2.IRaidDeviceSetter); ok {
|
||||
mdadmDriver.SetDevicesForAdapter(dConf.Adapter, devs)
|
||||
}
|
||||
}
|
||||
|
||||
if err := raiddrivers.BuildRaid(raidDrv, dConf.Configs, adapter); err != nil {
|
||||
return nil, fmt.Errorf("Build %s raid failed: %v", raidDrv.GetName(), err)
|
||||
}
|
||||
@@ -2721,7 +2795,7 @@ func (s *SBaremetalServer) DoDiskConfig(term *ssh.Client) (*disktool.SSHPartitio
|
||||
maxTries := 60
|
||||
for tried := 0; !tool.IsAllDisksReady() && tried < maxTries; tried++ {
|
||||
time.Sleep(5 * time.Second)
|
||||
tool.RetrieveDiskInfo()
|
||||
tool.RetrieveDiskInfo(matcher)
|
||||
log.Warningf("disktool not ready string: %s", tool.DebugString())
|
||||
}
|
||||
|
||||
@@ -2746,6 +2820,10 @@ func (s *SBaremetalServer) DoDiskUnconfig(term *ssh.Client) error {
|
||||
}
|
||||
|
||||
func (s *SBaremetalServer) DoEraseDisk(term *ssh.Client) error {
|
||||
// soft raid should stop mdadm first
|
||||
if err := mdadm.CleanRaid(term); err != nil {
|
||||
return err
|
||||
}
|
||||
cmd := "/lib/mos/partdestroy.sh"
|
||||
_, err := term.Run(cmd)
|
||||
return err
|
||||
@@ -2775,10 +2853,10 @@ func (s *SBaremetalServer) doCreateRoot(term *ssh.Client, devName string, disabl
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SBaremetalServer) DoPartitionDisk(tool *disktool.SSHPartitionTool, term *ssh.Client, disableImageCache bool) ([]*disktool.Partition, error) {
|
||||
func (s *SBaremetalServer) DoPartitionDisk(tool *disktool.SSHPartitionTool, term *ssh.Client, disableImageCache bool) (*disktool.DiskPartitions, []*disktool.Partition, error) {
|
||||
raid, nonRaid, pcie, err := detect_storages.DetectStorageInfo(term, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, errors.Wrap(err, "DetectStorageInfo")
|
||||
}
|
||||
storages := make([]*baremetal.BaremetalStorage, 0)
|
||||
storages = append(storages, raid...)
|
||||
@@ -2800,33 +2878,35 @@ func (s *SBaremetalServer) DoPartitionDisk(tool *disktool.SSHPartitionTool, term
|
||||
|
||||
disks, _ := s.desc.GetArray("disks")
|
||||
if len(disks) == 0 {
|
||||
return nil, errors.Error("Empty disks in desc")
|
||||
return nil, nil, errors.Error("Empty disks in desc")
|
||||
}
|
||||
|
||||
rootImageId := s.GetRootTemplateId()
|
||||
diskOffset := 0
|
||||
rootDisk := tool.GetRootDisk()
|
||||
log.Infof("root disk name %s", rootDisk.GetDevName())
|
||||
if len(rootImageId) > 0 {
|
||||
rootDisk := disks[0]
|
||||
rootSize, _ := rootDisk.Int("size")
|
||||
err = s.doCreateRoot(term, tool.GetRootDisk().GetDevName(), disableImageCache)
|
||||
rootDiskObj := disks[0]
|
||||
rootSize, _ := rootDiskObj.Int("size")
|
||||
err = s.doCreateRoot(term, rootDisk.GetDevName(), disableImageCache)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed to create root")
|
||||
return rootDisk, nil, errors.Wrap(err, "Failed to create root")
|
||||
}
|
||||
tool.RetrievePartitionInfo()
|
||||
parts := tool.GetPartitions()
|
||||
if len(parts) == 0 {
|
||||
return nil, errors.Error("Root disk create failed, no partitions")
|
||||
return rootDisk, nil, errors.Error("Root disk create failed, no partitions")
|
||||
}
|
||||
log.Infof("Resize root to %d MB", rootSize)
|
||||
if err := tool.ResizePartition(0, rootSize); err != nil {
|
||||
return nil, errors.Wrapf(err, "Fail to resize root to %d", rootSize)
|
||||
return rootDisk, nil, errors.Wrapf(err, "Fail to resize root to %d", rootSize)
|
||||
}
|
||||
diskOffset = 1
|
||||
} else {
|
||||
tool.RetrievePartitionInfo()
|
||||
parts := tool.GetPartitions()
|
||||
if len(parts) > 0 {
|
||||
return nil, errors.Error("should no partition!!!")
|
||||
return rootDisk, nil, errors.Error("should no partition!!!")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2841,16 +2921,16 @@ func (s *SBaremetalServer) DoPartitionDisk(tool *disktool.SSHPartitionTool, term
|
||||
driver, _ := disk.GetString("driver")
|
||||
log.Infof("Create partition %d %s", sz, fs)
|
||||
if err := tool.CreatePartition(-1, sz, fs, true, driver, uuid); err != nil {
|
||||
return nil, errors.Wrapf(err, "Fail to create disk %s", disk.String())
|
||||
return rootDisk, nil, errors.Wrapf(err, "Fail to create disk %s", disk.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
log.Infof("Finish create partitions")
|
||||
|
||||
return tool.GetPartitions(), nil
|
||||
return rootDisk, tool.GetPartitions(), nil
|
||||
}
|
||||
|
||||
func (s *SBaremetalServer) DoRebuildRootDisk(tool *disktool.SSHPartitionTool, term *ssh.Client, disableImageCache bool) ([]*disktool.Partition, error) {
|
||||
func (s *SBaremetalServer) DoRebuildRootDisk(tool *disktool.SSHPartitionTool, term *ssh.Client, disableImageCache bool) (*disktool.DiskPartitions, []*disktool.Partition, error) {
|
||||
// raid, nonRaid, pcie, err := detect_storages.DetectStorageInfo(term, false)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
@@ -2875,7 +2955,7 @@ func (s *SBaremetalServer) DoRebuildRootDisk(tool *disktool.SSHPartitionTool, te
|
||||
|
||||
disks, _ := s.desc.GetArray("disks")
|
||||
if len(disks) == 0 {
|
||||
return nil, fmt.Errorf("Empty disks in desc")
|
||||
return nil, nil, fmt.Errorf("Empty disks in desc")
|
||||
}
|
||||
|
||||
rootDisk := disks[0]
|
||||
@@ -2883,16 +2963,16 @@ func (s *SBaremetalServer) DoRebuildRootDisk(tool *disktool.SSHPartitionTool, te
|
||||
rd := tool.GetRootDisk()
|
||||
err := s.doCreateRoot(term, rd.GetDevName(), disableImageCache)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to create root: %v", err)
|
||||
return rd, nil, fmt.Errorf("Failed to create root: %v", err)
|
||||
}
|
||||
tool.RetrievePartitionInfo()
|
||||
if err := rd.ReInitInfo(); err != nil {
|
||||
return nil, errors.Wrap(err, "Reinit root disk after create root")
|
||||
return rd, nil, errors.Wrap(err, "Reinit root disk after create root")
|
||||
}
|
||||
|
||||
log.Infof("Resize root to %d MB", rootSize)
|
||||
if err := rd.ResizePartition(rootSize); err != nil {
|
||||
return nil, fmt.Errorf("Fail to resize root to %d, err: %v", rootSize, err)
|
||||
return rd, nil, fmt.Errorf("Fail to resize root to %d, err: %v", rootSize, err)
|
||||
}
|
||||
if len(disks) > 1 {
|
||||
for _, disk := range disks[1:] {
|
||||
@@ -2919,10 +2999,10 @@ func (s *SBaremetalServer) DoRebuildRootDisk(tool *disktool.SSHPartitionTool, te
|
||||
for _, d := range restDisks {
|
||||
parts = append(parts, d.GetPartitions()...)
|
||||
}
|
||||
return parts, nil
|
||||
return rd, parts, nil
|
||||
}
|
||||
|
||||
func (s *SBaremetalServer) SyncPartitionSize(term *ssh.Client, parts []*disktool.Partition) ([]jsonutils.JSONObject, error) {
|
||||
func (s *SBaremetalServer) SyncPartitionSize(term *ssh.Client, rootDisk *disktool.DiskPartitions, parts []*disktool.Partition) ([]jsonutils.JSONObject, error) {
|
||||
disks, _ := s.desc.GetArray("disks")
|
||||
|
||||
// calculate root partitions count
|
||||
@@ -2934,27 +3014,35 @@ func (s *SBaremetalServer) SyncPartitionSize(term *ssh.Client, parts []*disktool
|
||||
rootParts := parts[0:rootPartsCnt]
|
||||
dataParts := parts[rootPartsCnt:]
|
||||
idx := 0
|
||||
|
||||
// set root disk attributes that returns to region service
|
||||
size := (rootParts[len(rootParts)-1].GetEnd() + 1) * 512 / 1024 / 1024
|
||||
disks[idx].(*jsonutils.JSONDict).Set("size", jsonutils.NewInt(int64(size)))
|
||||
rootDiskObj := disks[idx].(*jsonutils.JSONDict)
|
||||
rootDiskObj.Set("size", jsonutils.NewInt(int64(size)))
|
||||
rootDiskObj.Set("pci_path", jsonutils.NewString(rootDisk.GetPCIPath()))
|
||||
|
||||
idx += 1
|
||||
for _, p := range dataParts {
|
||||
sizeMB, err := p.GetSizeMB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "GetSizeMB")
|
||||
}
|
||||
disks[idx].(*jsonutils.JSONDict).Set("size", jsonutils.NewInt(int64(sizeMB)))
|
||||
disks[idx].(*jsonutils.JSONDict).Set("dev", jsonutils.NewString(p.GetDev()))
|
||||
idx++
|
||||
}
|
||||
s.desc.Set("disks", jsonutils.NewArray(disks...))
|
||||
return disks, nil
|
||||
}
|
||||
|
||||
func (s *SBaremetalServer) DoDeploy(tool *disktool.SSHPartitionTool, term *ssh.Client, data jsonutils.JSONObject, isInit bool) (jsonutils.JSONObject, error) {
|
||||
publicKey := deployapi.GetKeys(data)
|
||||
isRandomPassword := false
|
||||
password, _ := data.GetString("password")
|
||||
resetPassword := jsonutils.QueryBoolean(data, "reset_password", false)
|
||||
if resetPassword && len(password) == 0 {
|
||||
password = seclib.RandomPassword(12)
|
||||
isRandomPassword = true
|
||||
}
|
||||
deployArray := make([]*deployapi.DeployContent, 0)
|
||||
if data.Contains("deploys") {
|
||||
@@ -2965,7 +3053,7 @@ func (s *SBaremetalServer) DoDeploy(tool *disktool.SSHPartitionTool, term *ssh.C
|
||||
}
|
||||
userData, _ := s.desc.GetString("user_data")
|
||||
deployInfo := deployapi.NewDeployInfo(publicKey, deployArray,
|
||||
password, isInit, true, o.Options.LinuxDefaultRootUser, o.Options.WindowsDefaultAdminUser, false, "",
|
||||
password, isRandomPassword, isInit, true, o.Options.LinuxDefaultRootUser, o.Options.WindowsDefaultAdminUser, false, "",
|
||||
false, "",
|
||||
userData,
|
||||
)
|
||||
|
||||
@@ -180,6 +180,25 @@ func (q *TaskQueue) AppendTask(task ITask) *TaskQueue {
|
||||
return q
|
||||
}
|
||||
|
||||
func (q *TaskQueue) ClearTasks() {
|
||||
for {
|
||||
existTask := q.PopTask()
|
||||
if existTask != nil {
|
||||
log.Warningf("Clear task %s", existTask.GetName())
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (q *TaskQueue) DebugString() string {
|
||||
str := ""
|
||||
for e := q.objList.Front(); e != nil; e = e.Next() {
|
||||
str += fmt.Sprintf("%s, ", e.Value.(ITask).GetName())
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
type TaskFactory func(userCred mcclient.TokenCredential, bm IBaremetal, taskId string, data jsonutils.JSONObject) ITask
|
||||
|
||||
type SBaremetalTaskBase struct {
|
||||
|
||||
@@ -54,22 +54,23 @@ func (self *SBaremetalServerCreateTask) RemoveEFIOSEntry() bool {
|
||||
}
|
||||
|
||||
func (self *SBaremetalServerCreateTask) DoDeploys(ctx context.Context, term *ssh.Client) (jsonutils.JSONObject, error) {
|
||||
if err := self.Baremetal.GetServer().DoEraseDisk(term); err != nil {
|
||||
return nil, self.onError(ctx, term, err)
|
||||
}
|
||||
time.Sleep(2 * time.Second)
|
||||
// Build raid
|
||||
tool, err := self.Baremetal.GetServer().DoDiskConfig(term)
|
||||
if err != nil {
|
||||
return nil, self.onError(ctx, term, err)
|
||||
}
|
||||
time.Sleep(2 * time.Second)
|
||||
if err := self.Baremetal.GetServer().DoEraseDisk(term); err != nil {
|
||||
return nil, self.onError(ctx, term, err)
|
||||
}
|
||||
time.Sleep(2 * time.Second)
|
||||
parts, err := self.Baremetal.GetServer().DoPartitionDisk(tool, term, self.IsDisableImageCache())
|
||||
rootDisk, parts, err := self.Baremetal.GetServer().DoPartitionDisk(tool, term, self.IsDisableImageCache())
|
||||
if err != nil {
|
||||
return nil, self.onError(ctx, term, err)
|
||||
}
|
||||
data := jsonutils.NewDict()
|
||||
disks, err := self.Baremetal.GetServer().SyncPartitionSize(term, parts)
|
||||
|
||||
disks, err := self.Baremetal.GetServer().SyncPartitionSize(term, rootDisk, parts)
|
||||
if err != nil {
|
||||
return nil, self.onError(ctx, term, err)
|
||||
}
|
||||
|
||||
@@ -26,6 +26,10 @@ import (
|
||||
|
||||
var _ IServerBaseDeployTask = new(SBaremetalServerDestroyTask)
|
||||
|
||||
const (
|
||||
BAREMETAL_SERVER_DESTROY_TASK = "BaremetalServerDestroyTask"
|
||||
)
|
||||
|
||||
type SBaremetalServerDestroyTask struct {
|
||||
SBaremetalServerBaseDeployTask
|
||||
}
|
||||
@@ -45,7 +49,7 @@ func NewBaremetalServerDestroyTask(
|
||||
}
|
||||
|
||||
func (self *SBaremetalServerDestroyTask) GetName() string {
|
||||
return "BaremetalServerDestroyTask"
|
||||
return BAREMETAL_SERVER_DESTROY_TASK
|
||||
}
|
||||
|
||||
func (self *SBaremetalServerDestroyTask) RemoveEFIOSEntry() bool {
|
||||
|
||||
@@ -50,10 +50,10 @@ type IBaremetal interface {
|
||||
|
||||
SyncStatus(ctx context.Context, status, reason string)
|
||||
AutoSyncStatus(ctx context.Context)
|
||||
SyncAllStatus(ctx context.Context, status string)
|
||||
SyncAllStatus(ctx context.Context, status types.PowerStatus)
|
||||
AutoSyncAllStatus(ctx context.Context)
|
||||
|
||||
GetPowerStatus() (string, error)
|
||||
GetPowerStatus() (types.PowerStatus, error)
|
||||
DoPowerShutdown(soft bool) error
|
||||
DoPXEBoot() error
|
||||
// DoDiskBoot() error
|
||||
|
||||
@@ -58,11 +58,11 @@ func (self *SBaremetalServerRebuildTask) DoDeploys(ctx context.Context, term *ss
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "NewConfigedSSHPartitionTool")
|
||||
}
|
||||
parts, err := self.Baremetal.GetServer().DoRebuildRootDisk(tool, term, self.IsDisableImageCache())
|
||||
rootDisk, parts, err := self.Baremetal.GetServer().DoRebuildRootDisk(tool, term, self.IsDisableImageCache())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Rebuild root disk: %v", err)
|
||||
}
|
||||
disks, err := self.Baremetal.GetServer().SyncPartitionSize(term, parts)
|
||||
disks, err := self.Baremetal.GetServer().SyncPartitionSize(term, rootDisk, parts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("SyncPartitionSize: %v", err)
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ func (self *SBaremetalResetBMCTask) WaitForBMCReady(ctx context.Context, args in
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if status != "" && status == types.POWER_STATUS_ON {
|
||||
if status != "" && status == string(types.POWER_STATUS_ON) {
|
||||
ExecuteTask(self, nil)
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -31,10 +31,10 @@ type IBaremetalServer interface {
|
||||
DoDiskUnconfig(term *ssh.Client) error
|
||||
DoDiskConfig(term *ssh.Client) (*disktool.SSHPartitionTool, error)
|
||||
DoEraseDisk(term *ssh.Client) error
|
||||
DoPartitionDisk(tool *disktool.SSHPartitionTool, term *ssh.Client, disableImageCache bool) ([]*disktool.Partition, error)
|
||||
DoPartitionDisk(tool *disktool.SSHPartitionTool, term *ssh.Client, disableImageCache bool) (*disktool.DiskPartitions, []*disktool.Partition, error)
|
||||
NewConfigedSSHPartitionTool(term *ssh.Client) (*disktool.SSHPartitionTool, error)
|
||||
DoRebuildRootDisk(tool *disktool.SSHPartitionTool, term *ssh.Client, disableImageCache bool) ([]*disktool.Partition, error)
|
||||
SyncPartitionSize(term *ssh.Client, parts []*disktool.Partition) ([]jsonutils.JSONObject, error)
|
||||
DoRebuildRootDisk(tool *disktool.SSHPartitionTool, term *ssh.Client, disableImageCache bool) (*disktool.DiskPartitions, []*disktool.Partition, error)
|
||||
SyncPartitionSize(term *ssh.Client, rootDisk *disktool.DiskPartitions, parts []*disktool.Partition) ([]jsonutils.JSONObject, error)
|
||||
DoDeploy(tool *disktool.SSHPartitionTool, term *ssh.Client, data jsonutils.JSONObject, isInit bool) (jsonutils.JSONObject, error)
|
||||
SaveDesc(desc jsonutils.JSONObject) error
|
||||
GetNics() []types.SServerNic
|
||||
|
||||
@@ -17,8 +17,10 @@ package disktool
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/utils"
|
||||
@@ -224,10 +226,11 @@ type DiskPartitions struct {
|
||||
rotate bool
|
||||
desc string
|
||||
label string
|
||||
pciPath string
|
||||
partitions []*Partition
|
||||
}
|
||||
|
||||
func newDiskPartitions(driver string, adapter int, raidConfig string, sizeMB int64, blockSize int64, diskType string, tool *PartitionTool) *DiskPartitions {
|
||||
func newDiskPartitions(driver string, adapter int, raidConfig string, sizeMB int64, blockSize int64, diskType string, softRaidIdx *int, tool *PartitionTool) *DiskPartitions {
|
||||
ps := new(DiskPartitions)
|
||||
ps.driver = driver
|
||||
ps.adapter = adapter
|
||||
@@ -237,9 +240,32 @@ func newDiskPartitions(driver string, adapter int, raidConfig string, sizeMB int
|
||||
ps.blockSize = blockSize
|
||||
ps.diskType = diskType
|
||||
ps.partitions = make([]*Partition, 0)
|
||||
|
||||
// soft raid, mdadm
|
||||
if softRaidIdx != nil {
|
||||
ps.GetMdadmInfo(softRaidIdx)
|
||||
}
|
||||
return ps
|
||||
}
|
||||
|
||||
func (ps *DiskPartitions) GetMdadmInfo(softRaidIdx *int) {
|
||||
devLinkName := fmt.Sprintf("/dev/md/md%d", *softRaidIdx)
|
||||
devLinkNickname := fmt.Sprintf("/dev/md/md%d_0", *softRaidIdx)
|
||||
cmd := fmt.Sprintf("readlink -f $(test -e %s && echo %s || echo %s)", devLinkName, devLinkName, devLinkNickname)
|
||||
out, err := ps.tool.Run(cmd)
|
||||
if err != nil || len(out) == 0 {
|
||||
log.Errorf("failed readlink of %s: %s", devLinkName, err)
|
||||
return
|
||||
}
|
||||
|
||||
ps.dev = strings.TrimSpace(out[0])
|
||||
ps.devName = ps.dev
|
||||
uuid, sectors := ps.tool.GetMdadmUuidAndSector(ps.dev)
|
||||
ps.pciPath = uuid
|
||||
ps.sectors = sectors
|
||||
ps.blockSize = 512
|
||||
}
|
||||
|
||||
func (p *DiskPartitions) IsRaidDriver() bool {
|
||||
return utils.IsInStringArray(p.driver, []string{
|
||||
baremetal.DISK_DRIVER_MEGARAID,
|
||||
@@ -253,7 +279,13 @@ func (p *DiskPartitions) GetDev() string {
|
||||
return p.dev
|
||||
}
|
||||
|
||||
func (p *DiskPartitions) SetInfo(info *types.SDiskInfo) *DiskPartitions {
|
||||
func getPCIPathPrefix(input string) string {
|
||||
input = strings.TrimSpace(input)
|
||||
parts := strings.Split(input, "/")
|
||||
return strings.Join(parts[0:len(parts)-2], "/")
|
||||
}
|
||||
|
||||
func (p *DiskPartitions) SetInfo(info *types.SDiskInfo) (*DiskPartitions, error) {
|
||||
p.dev = fmt.Sprintf("/dev/%s", info.Dev)
|
||||
p.devName = info.Dev
|
||||
p.sectors = info.Sector
|
||||
@@ -262,7 +294,17 @@ func (p *DiskPartitions) SetInfo(info *types.SDiskInfo) *DiskPartitions {
|
||||
if p.blockSize == 4096 {
|
||||
p.sectors = (p.sectors >> 3)
|
||||
}
|
||||
return p
|
||||
|
||||
// /sys/block/sda => /sys/devices/pci0000:00/0000:00:04.0/virtio1/host0/target0:0:0/0:0:0:0/block/sda
|
||||
// /sys/block/nvme1n1 => /sys/devices/pci0000:00/0000:00:1a.0/0000:03:00.0/nvme/nvme1/nvme1n1
|
||||
outputs, err := p.Run(fmt.Sprintf("readlink -f /sys/block/%s", info.Dev))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to read device %s pci path", p.dev)
|
||||
}
|
||||
if len(outputs) > 0 {
|
||||
p.pciPath = getPCIPathPrefix(outputs[0])
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (p *DiskPartitions) ReInitInfo() error {
|
||||
@@ -273,7 +315,9 @@ func (p *DiskPartitions) ReInitInfo() error {
|
||||
}
|
||||
for _, disk := range sysutils.ParseDiskInfo(lines, p.driver) {
|
||||
if disk.Dev == p.GetDevName() {
|
||||
p.SetInfo(disk)
|
||||
if _, err := p.SetInfo(disk); err != nil {
|
||||
return errors.Wrapf(err, "set info of disk %v", disk)
|
||||
}
|
||||
}
|
||||
}
|
||||
return p.RetrievePartitionInfo()
|
||||
@@ -304,7 +348,7 @@ func (ps *DiskPartitions) IsReady() bool {
|
||||
|
||||
func (ps *DiskPartitions) GetDevName() string {
|
||||
devName := ps.devName
|
||||
if !ps.IsRaidDriver() || ps.raidConfig == baremetal.DISK_CONF_NONE {
|
||||
if ps.raidConfig == baremetal.DISK_CONF_NONE {
|
||||
return devName
|
||||
}
|
||||
raidDrv, err := raiddrivers.GetDriverWithInit(ps.driver, ps.tool.runner.Term())
|
||||
@@ -326,6 +370,10 @@ func (ps *DiskPartitions) GetDevName() string {
|
||||
return devName
|
||||
}
|
||||
|
||||
func (ps *DiskPartitions) GetPCIPath() string {
|
||||
return ps.pciPath
|
||||
}
|
||||
|
||||
func (ps *DiskPartitions) RetrievePartitionInfo() error {
|
||||
ps.partitions = make([]*Partition, 0)
|
||||
cmd := []string{"parted", "-s", ps.dev, "--", "unit", "s", "print"}
|
||||
@@ -664,14 +712,15 @@ func (tool *PartitionTool) parseLsDisk(lines []string, driver string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (tool *PartitionTool) FetchDiskConfs(diskConfs []baremetal.DiskConfiguration, rootMatcher *api.BaremetalRootDiskMatcher) *PartitionTool {
|
||||
func (tool *PartitionTool) FetchDiskConfs(diskConfs []baremetal.DiskConfiguration) *PartitionTool {
|
||||
for _, d := range diskConfs {
|
||||
disk := newDiskPartitions(d.Driver, d.Adapter, d.RaidConfig, d.Size, d.Block, d.DiskType, tool)
|
||||
disk := newDiskPartitions(d.Driver, d.Adapter, d.RaidConfig, d.Size, d.Block, d.DiskType, d.SoftRaidIdx, tool)
|
||||
tool.disks = append(tool.disks, disk)
|
||||
isSoftRaid := d.RaidConfig != baremetal.DISK_CONF_NONE
|
||||
var key string
|
||||
if d.Driver == baremetal.DISK_DRIVER_LINUX {
|
||||
if d.Driver == baremetal.DISK_DRIVER_LINUX && !isSoftRaid {
|
||||
key = NONRAID_DRIVER
|
||||
} else if d.Driver == baremetal.DISK_DRIVER_PCIE {
|
||||
} else if d.Driver == baremetal.DISK_DRIVER_PCIE && !isSoftRaid {
|
||||
key = PCIE_DRIVER
|
||||
} else {
|
||||
key = RAID_DRVIER
|
||||
@@ -681,16 +730,10 @@ func (tool *PartitionTool) FetchDiskConfs(diskConfs []baremetal.DiskConfiguratio
|
||||
}
|
||||
tool.diskTable[key] = append(tool.diskTable[key], disk)
|
||||
}
|
||||
// reorder tool.disks
|
||||
if rootMatcher != nil {
|
||||
tool.reorderRootDisk(rootMatcher)
|
||||
}
|
||||
return tool
|
||||
}
|
||||
|
||||
func (tool *PartitionTool) reorderRootDisk(matcher *api.BaremetalRootDiskMatcher) {
|
||||
var rootDiskIdx = 0
|
||||
|
||||
isDiskMatch := func(disk *DiskPartitions, matcher *api.BaremetalRootDiskMatcher) bool {
|
||||
if matcher.Device != "" {
|
||||
if disk.dev == matcher.Device {
|
||||
@@ -710,16 +753,25 @@ func (tool *PartitionTool) reorderRootDisk(matcher *api.BaremetalRootDiskMatcher
|
||||
return true
|
||||
}
|
||||
}
|
||||
if matcher.PCIPath != "" {
|
||||
if disk.pciPath == matcher.PCIPath {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var rootDiskStr string
|
||||
var rootDiskIdx = 0
|
||||
|
||||
for idx, disk := range tool.disks {
|
||||
if isDiskMatch(disk, matcher) {
|
||||
rootDiskIdx = idx
|
||||
rootDiskStr = disk.String()
|
||||
break
|
||||
}
|
||||
}
|
||||
log.Infof("Select %d as root disk", rootDiskIdx)
|
||||
log.Infof("Select %d %q as root disk by matcher: %s", rootDiskIdx, rootDiskStr, jsonutils.Marshal(matcher))
|
||||
newDisks := make([]*DiskPartitions, 0)
|
||||
newDisks = append(newDisks, tool.disks[rootDiskIdx])
|
||||
for idx := range tool.disks {
|
||||
@@ -741,7 +793,42 @@ func (tool *PartitionTool) IsAllDisksReady() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (tool *PartitionTool) RetrieveDiskInfo() error {
|
||||
func (tool *PartitionTool) GetMdadmUuidAndSector(devPath string) (string, int64) {
|
||||
var uuid string
|
||||
var sectorsRet int64
|
||||
// get md uuid as pci path
|
||||
cmd := fmt.Sprintf("/sbin/mdadm --detail %s | grep UUID", devPath)
|
||||
output, err := tool.Run(cmd)
|
||||
if err == nil && len(output) > 0 {
|
||||
uuidSeg := output[0]
|
||||
segs := strings.SplitN(strings.TrimSpace(uuidSeg), ":", 2)
|
||||
if len(segs) == 2 {
|
||||
uuid = strings.TrimSpace(segs[1])
|
||||
}
|
||||
}
|
||||
|
||||
// get block size
|
||||
cmd = fmt.Sprintf("blockdev --getsz %s 2>/dev/null || echo 0", devPath)
|
||||
output, err = tool.Run(cmd)
|
||||
if err == nil && len(output) > 0 {
|
||||
if sectors, err := strconv.ParseInt(strings.TrimSpace(output[0]), 10, 64); err == nil {
|
||||
sectorsRet = sectors
|
||||
}
|
||||
}
|
||||
return uuid, sectorsRet
|
||||
}
|
||||
|
||||
func (tool *PartitionTool) RetrieveDiskInfo(rootMatcher *api.BaremetalRootDiskMatcher) error {
|
||||
for _, disk := range tool.disks {
|
||||
if baremetal.DISK_DRIVERS_SOFT_RAID.Has(disk.driver) && disk.raidConfig != baremetal.DISK_CONF_NONE {
|
||||
log.Infof("Soft raid mdadm set diskinfo dev %s", disk.dev)
|
||||
uuid, sectors := tool.GetMdadmUuidAndSector(disk.dev)
|
||||
disk.pciPath = uuid
|
||||
disk.sectors = sectors
|
||||
disk.blockSize = 512
|
||||
}
|
||||
}
|
||||
|
||||
for _, driver := range []string{RAID_DRVIER, NONRAID_DRIVER, PCIE_DRIVER} {
|
||||
cmd := fmt.Sprintf("/lib/mos/lsdisk --%s", driver)
|
||||
ret, err := tool.Run(cmd)
|
||||
@@ -750,6 +837,10 @@ func (tool *PartitionTool) RetrieveDiskInfo() error {
|
||||
}
|
||||
tool.parseLsDisk(ret, driver)
|
||||
}
|
||||
// reorder tool.disks
|
||||
if rootMatcher != nil {
|
||||
tool.reorderRootDisk(rootMatcher)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -837,8 +928,8 @@ func newSSHPartitionTool(term *ssh.Client) *SSHPartitionTool {
|
||||
|
||||
func NewSSHPartitionTool(term *ssh.Client, layouts []baremetal.Layout, rootMatcher *api.BaremetalRootDiskMatcher) (*SSHPartitionTool, error) {
|
||||
tool := newSSHPartitionTool(term)
|
||||
tool.FetchDiskConfs(baremetal.GetDiskConfigurations(layouts), rootMatcher)
|
||||
if err := tool.RetrieveDiskInfo(); err != nil {
|
||||
tool.FetchDiskConfs(baremetal.GetDiskConfigurations(layouts))
|
||||
if err := tool.RetrieveDiskInfo(rootMatcher); err != nil {
|
||||
return nil, errors.Wrapf(err, "RetrieveDiskInfo")
|
||||
}
|
||||
return tool, nil
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
package disktool
|
||||
|
||||
import "testing"
|
||||
|
||||
// TODO: use mock ssh server backend test disktool
|
||||
/*
|
||||
import (
|
||||
@@ -64,3 +66,26 @@ func TestSSHCreate(t *testing.T) {
|
||||
t.Errorf("Failed to resize fs: %v", err)
|
||||
}
|
||||
}*/
|
||||
|
||||
func Test_getPCIPathPrefix(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
input: "/sys/devices/pci0000:00/0000:00:02.2/0000:02:00.0/host0/target0:1:0/0:1:0:0/block/sda",
|
||||
want: "/sys/devices/pci0000:00/0000:00:02.2/0000:02:00.0/host0/target0:1:0/0:1:0:0",
|
||||
},
|
||||
{
|
||||
input: "/sys/devices/pci0000:00/0000:00:06.0/0000:02:00.0/nvme/nvme0/nvme0n1",
|
||||
want: "/sys/devices/pci0000:00/0000:00:06.0/0000:02:00.0/nvme",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.input, func(t *testing.T) {
|
||||
if got := getPCIPathPrefix(tt.input); got != tt.want {
|
||||
t.Errorf("getPCIPathPrefix() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,8 +42,8 @@ menuentry 'YunionOS for PXE' --class os {
|
||||
|
||||
var (
|
||||
BOOT_EFI_MATCHER = "(hd*,gpt*)/EFI/BOOT/BOOTX64.EFI (hd*,msdos*)/EFI/BOOT/BOOTX64.EFI (hd*,gpt*)/EFI/BOOT/BOOTAA64.EFI (hd*,msdos*)/EFI/BOOT/BOOTAA64.EFI"
|
||||
GRUB_EFI_MATCHER = "(md*)/EFI/*/shimx64.efi (md*)/EFI/*/grubx64.efi (hd*,gpt*)/EFI/*/shimx64.efi (hd*,msdos*)/EFI/*/shimx64.efi (hd*,gpt*)/EFI/*/grubx64.efi (hd*,mosdos*)/EFI/*/grubx64.efi (hd*,gpt*)/EFI/*/shimaa64.efi (hd*,msdos*)/EFI/*/shimaa64.efi (hd*,gpt*)/EFI/*/grubaa64.efi (hd*,mosdos*)/EFI/*/grubaa64.efi"
|
||||
GRUB_CFG_MATCHER = "(md*)/boot/*/grub.cfg (md*)/*/grub.cfg (md*)/grub.cfg (md*)/EFI/*/grub.cfg (md*)/EFI/*/*/grub.cfg (hd*,gpt*)/boot/*/grub.cfg (hd*,gpt*)/*/grub.cfg (hd*,gpt*)/grub.cfg (hd*,gpt*)/EFI/*/grub.cfg (hd*,gpt*)/EFI/*/*/grub.cfg (hd*,mosdos*)/boot/*/grub.cfg (hd*,mosdos*)/*/grub.cfg (hd*,mosdos*)/grub.cfg (hd*,mosdos*)/EFI/*/grub.cfg (hd*,mosdos*)/EFI/*/*/grub.cfg"
|
||||
GRUB_EFI_MATCHER = "(md*)/EFI/*/shimx64.efi (md*)/EFI/*/grubx64.efi (hd*,gpt*)/EFI/*/shimx64.efi (hd*,msdos*)/EFI/*/shimx64.efi (hd*,gpt*)/EFI/*/grubx64.efi (hd*,msdos*)/EFI/*/grubx64.efi (hd*,gpt*)/EFI/*/shimaa64.efi (hd*,msdos*)/EFI/*/shimaa64.efi (hd*,gpt*)/EFI/*/grubaa64.efi (hd*,msdos*)/EFI/*/grubaa64.efi"
|
||||
GRUB_CFG_MATCHER = "(md*)/boot/*/grub.cfg (md*)/*/grub.cfg (md*)/grub.cfg (md*)/EFI/*/grub.cfg (md*)/EFI/*/*/grub.cfg (hd*,gpt*)/boot/*/grub.cfg (hd*,gpt*)/*/grub.cfg (hd*,gpt*)/grub.cfg (hd*,gpt*)/EFI/*/grub.cfg (hd*,gpt*)/EFI/*/*/grub.cfg (hd*,msdos*)/boot/*/grub.cfg (hd*,msdos*)/*/grub.cfg (hd*,msdos*)/grub.cfg (hd*,msdos*)/EFI/*/grub.cfg (hd*,msdos*)/EFI/*/*/grub.cfg"
|
||||
)
|
||||
|
||||
// REF: https://github.com/bluebanquise/infrastructure/blob/master/packages/bluebanquise-ipxe/grub2-efi-autofind.cfg
|
||||
|
||||
@@ -520,7 +520,7 @@ func DoReboot(exector IPMIExecutor) error {
|
||||
}
|
||||
|
||||
isValidStatus := func(s string) bool {
|
||||
return utils.IsInStringArray(s, []string{types.POWER_STATUS_ON, types.POWER_STATUS_OFF})
|
||||
return utils.IsInStringArray(s, []string{string(types.POWER_STATUS_ON), string(types.POWER_STATUS_OFF)})
|
||||
}
|
||||
|
||||
for tried := 0; !isValidStatus(status) && tried <= maxTries; tried++ {
|
||||
@@ -536,7 +536,7 @@ func DoReboot(exector IPMIExecutor) error {
|
||||
}
|
||||
|
||||
// do shutdown
|
||||
if status == types.POWER_STATUS_ON {
|
||||
if status == string(types.POWER_STATUS_ON) {
|
||||
if err := DoHardShutdown(exector); err != nil {
|
||||
log.Errorf("DoHardShutdown: %v", err)
|
||||
}
|
||||
@@ -546,7 +546,7 @@ func DoReboot(exector IPMIExecutor) error {
|
||||
if err != nil {
|
||||
log.Errorf("DoReboot %d tries to get power status: %v", tried, err)
|
||||
}
|
||||
if status == types.POWER_STATUS_OFF {
|
||||
if status == string(types.POWER_STATUS_OFF) {
|
||||
break
|
||||
}
|
||||
time.Sleep(10 * time.Second)
|
||||
@@ -555,7 +555,7 @@ func DoReboot(exector IPMIExecutor) error {
|
||||
|
||||
// do power on
|
||||
status, _ = GetChassisPowerStatus(exector)
|
||||
for tried := 0; status != types.POWER_STATUS_ON && tried < maxTries; tried++ {
|
||||
for tried := 0; status != string(types.POWER_STATUS_ON) && tried < maxTries; tried++ {
|
||||
if err := DoPowerOn(exector); err != nil {
|
||||
log.Errorf("DoReboot %d tries to power on: %v", tried, err)
|
||||
}
|
||||
@@ -570,7 +570,7 @@ func DoReboot(exector IPMIExecutor) error {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Get power status after power on")
|
||||
}
|
||||
if status != types.POWER_STATUS_ON {
|
||||
if status != string(types.POWER_STATUS_ON) {
|
||||
return errors.Errorf("do reboot fail to poweron, current status: %s", status)
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/baremetal/utils/raid"
|
||||
_ "yunion.io/x/onecloud/pkg/baremetal/utils/raid/adaptec"
|
||||
_ "yunion.io/x/onecloud/pkg/baremetal/utils/raid/hpssactl"
|
||||
_ "yunion.io/x/onecloud/pkg/baremetal/utils/raid/mdadm"
|
||||
_ "yunion.io/x/onecloud/pkg/baremetal/utils/raid/megactl"
|
||||
_ "yunion.io/x/onecloud/pkg/baremetal/utils/raid/mvcli"
|
||||
_ "yunion.io/x/onecloud/pkg/baremetal/utils/raid/sas2iru"
|
||||
|
||||
@@ -45,6 +45,10 @@ type IRaidAdapter interface {
|
||||
PostBuildRaid() error
|
||||
}
|
||||
|
||||
type IRaidDeviceSetter interface {
|
||||
SetDevicesForAdapter(int, []*baremetal.BaremetalStorage)
|
||||
}
|
||||
|
||||
type IExecTerm interface {
|
||||
Run(cmds ...string) ([]string, error)
|
||||
RunWithInput(input io.Reader, cmds ...string) ([]string, error)
|
||||
|
||||
1
pkg/baremetal/utils/raid/mdadm/doc.go
Normal file
1
pkg/baremetal/utils/raid/mdadm/doc.go
Normal file
@@ -0,0 +1 @@
|
||||
package mdadm // import "yunion.io/x/onecloud/pkg/baremetal/utils/raid/mdadm"
|
||||
434
pkg/baremetal/utils/raid/mdadm/mdadm.go
Normal file
434
pkg/baremetal/utils/raid/mdadm/mdadm.go
Normal file
@@ -0,0 +1,434 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package mdadm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/baremetal/utils/raid"
|
||||
"yunion.io/x/onecloud/pkg/compute/baremetal"
|
||||
"yunion.io/x/onecloud/pkg/util/ssh"
|
||||
"yunion.io/x/onecloud/pkg/util/sysutils"
|
||||
)
|
||||
|
||||
const (
|
||||
MDADM_BIN = "/sbin/mdadm"
|
||||
)
|
||||
|
||||
func init() {
|
||||
raid.RegisterDriver(baremetal.DISK_DRIVER_LINUX, NewMdadmRaidLinux)
|
||||
raid.RegisterDriver(baremetal.DISK_DRIVER_PCIE, NewMdadmRaidPcie)
|
||||
}
|
||||
|
||||
type MdadmRaid struct {
|
||||
term raid.IExecTerm
|
||||
adapter *MdadmRaidAdapter
|
||||
driverName string
|
||||
}
|
||||
|
||||
func NewMdadmRaidLinux(term raid.IExecTerm) raid.IRaidDriver {
|
||||
return &MdadmRaid{
|
||||
term: term,
|
||||
driverName: baremetal.DISK_DRIVER_LINUX,
|
||||
}
|
||||
}
|
||||
|
||||
func NewMdadmRaidPcie(term raid.IExecTerm) raid.IRaidDriver {
|
||||
return &MdadmRaid{
|
||||
term: term,
|
||||
driverName: baremetal.DISK_DRIVER_PCIE,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *MdadmRaid) GetName() string {
|
||||
return r.driverName
|
||||
}
|
||||
|
||||
func (r *MdadmRaid) ParsePhyDevs() error {
|
||||
if r.adapter == nil {
|
||||
r.adapter = &MdadmRaidAdapter{
|
||||
raid: r,
|
||||
term: r.term,
|
||||
index: 0,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *MdadmRaid) SetDevicesForAdapter(adapterIdx int, devs []*baremetal.BaremetalStorage) {
|
||||
r.adapter.setDevices(devs)
|
||||
for i := range devs {
|
||||
devPath := path.Join("/dev", devs[i].Dev)
|
||||
cmd := fmt.Sprintf("%s --examine %s | grep UUID", MDADM_BIN, devPath)
|
||||
output, err := r.term.Run(cmd)
|
||||
if err == nil && len(output) > 0 {
|
||||
for _, line := range output {
|
||||
segs := strings.SplitN(strings.TrimSpace(line), ":", 2)
|
||||
if len(segs) == 2 {
|
||||
uuid := strings.TrimSpace(segs[1])
|
||||
cmd = fmt.Sprintf("%s --assemble --scan --uuid=%s", MDADM_BIN, uuid)
|
||||
output, err := r.term.Run(cmd)
|
||||
if err != nil {
|
||||
log.Errorf("faield assemble mdadm %s: %s", uuid, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *MdadmRaid) GetAdapters() []raid.IRaidAdapter {
|
||||
return []raid.IRaidAdapter{r.adapter}
|
||||
}
|
||||
|
||||
func (r *MdadmRaid) PreBuildRaid(confs []*api.BaremetalDiskConfig, adapterIdx int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func deviceHasRaid(devPath string, term *ssh.Client) bool {
|
||||
cmd := fmt.Sprintf("%s --examine %s 2>/dev/null || true", MDADM_BIN, devPath)
|
||||
output, err := term.Run(cmd)
|
||||
if err != nil {
|
||||
log.Errorf("examine device %s: %s", devPath, err)
|
||||
return false
|
||||
}
|
||||
|
||||
for _, line := range output {
|
||||
if strings.Contains(line, "mdadm") || strings.Contains(line, "ARRAY") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *MdadmRaid) CleanRaid() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func CleanMdadmPartitions(term *ssh.Client) {
|
||||
out, err := term.Run("ls -1 /dev/md/")
|
||||
if err != nil {
|
||||
log.Errorf("failed get md devices %s, %s", out, err)
|
||||
return
|
||||
}
|
||||
// destory mdadm soft raid
|
||||
for _, line := range out {
|
||||
dev := strings.TrimSpace(line)
|
||||
if !strings.HasPrefix(dev, "md") {
|
||||
continue
|
||||
}
|
||||
out, err = term.Run(fmt.Sprintf("dd if=/dev/zero of=/dev/md/%s bs=512 count=34", dev))
|
||||
if err != nil {
|
||||
log.Errorf("failed clean mdadm partitions %s %s", out, err)
|
||||
}
|
||||
out, err = term.Run(fmt.Sprintf("dd if=/dev/zero of=/dev/md/%s bs=512 count=34 seek=$(( $(blockdev --getsz /dev/md/%s) - 34 ))", dev, dev))
|
||||
if err != nil {
|
||||
log.Errorf("failed clean mdadm partitions %s %s", out, err)
|
||||
}
|
||||
out, err = term.Run(fmt.Sprintf("hdparm -z /dev/md/%s", dev))
|
||||
if err != nil {
|
||||
log.Errorf("failed clean mdadm partitions %s %s", out, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func CleanRaid(term *ssh.Client) error {
|
||||
CleanMdadmPartitions(term)
|
||||
|
||||
// stop md devices
|
||||
cmd := fmt.Sprintf("%s --stop --scan", MDADM_BIN)
|
||||
_, err := term.Run(cmd)
|
||||
if err != nil {
|
||||
log.Warningf("Stop md devices: %s", err)
|
||||
}
|
||||
|
||||
pcieRet, err := term.Run("/lib/mos/lsdisk --pcie")
|
||||
if err != nil {
|
||||
log.Warningf("Fail to retrieve PCIE DISK info %s", err)
|
||||
} else {
|
||||
pcieDiskInfo := sysutils.ParsePCIEDiskInfo(pcieRet)
|
||||
for i := range pcieDiskInfo {
|
||||
devPath := path.Join("/dev", pcieDiskInfo[i].Dev)
|
||||
if deviceHasRaid(devPath, term) {
|
||||
cmd := fmt.Sprintf("%s --zero-superblock --force %s", MDADM_BIN, devPath)
|
||||
out, err := term.Run(cmd)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "zero superblock on %s: %s", devPath, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nonraidRet, err := term.Run("/lib/mos/lsdisk --nonraid")
|
||||
if err != nil {
|
||||
log.Warningf("Fail to retrieve SCSI DISK info %s", err)
|
||||
} else {
|
||||
nonraidDiskInfo := sysutils.ParseSCSIDiskInfo(nonraidRet)
|
||||
for i := range nonraidDiskInfo {
|
||||
devPath := path.Join("/dev", nonraidDiskInfo[i].Dev)
|
||||
if deviceHasRaid(devPath, term) {
|
||||
cmd := fmt.Sprintf("%s --zero-superblock --force %s", MDADM_BIN, devPath)
|
||||
out, err := term.Run(cmd)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "zero superblock on %s: %s", devPath, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out, err := term.Run("rm /dev/md/*")
|
||||
if err != nil {
|
||||
log.Warningf("failed soft link at /dev/md %s", out)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type MdadmRaidAdapter struct {
|
||||
raid *MdadmRaid
|
||||
term raid.IExecTerm
|
||||
index int
|
||||
devs []*baremetal.BaremetalStorage
|
||||
}
|
||||
|
||||
func (a *MdadmRaidAdapter) GetIndex() int {
|
||||
return a.index
|
||||
}
|
||||
|
||||
func (a *MdadmRaidAdapter) PreBuildRaid(confs []*api.BaremetalDiskConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *MdadmRaidAdapter) GetLogicVolumes() ([]*raid.RaidLogicalVolume, error) {
|
||||
lvs := make([]*raid.RaidLogicalVolume, 0)
|
||||
cmd := "ls -1 /dev/md/* 2>/dev/null || true"
|
||||
output, err := a.term.Run(cmd)
|
||||
if err != nil {
|
||||
return lvs, nil
|
||||
}
|
||||
|
||||
for _, line := range output {
|
||||
line = strings.TrimSpace(line)
|
||||
if strings.HasPrefix(line, "/dev/md/md") {
|
||||
mdPath := line
|
||||
numStr := strings.TrimPrefix(line, "/dev/md/md")
|
||||
if strings.HasSuffix(numStr, "_0") {
|
||||
numStr = strings.TrimSuffix(numStr, "_0")
|
||||
}
|
||||
if num, err := strconv.Atoi(numStr); err == nil {
|
||||
res, err := a.term.Run(fmt.Sprintf("readlink -f %s", line))
|
||||
if err == nil && len(res) > 0 {
|
||||
mdPath = strings.TrimSpace(res[0])
|
||||
lv := &raid.RaidLogicalVolume{
|
||||
Index: num,
|
||||
Adapter: a.index,
|
||||
BlockDev: mdPath,
|
||||
}
|
||||
lvs = append(lvs, lv)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lvs, nil
|
||||
}
|
||||
|
||||
func (a *MdadmRaidAdapter) RemoveLogicVolumes() error {
|
||||
//cmd := fmt.Sprintf("%s --stop --scan", MDADM_BIN)
|
||||
//_, err := a.term.Run(cmd)
|
||||
//if err != nil {
|
||||
// log.Warningf("Stop md devices: %v", err)
|
||||
//}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *MdadmRaidAdapter) GetDevices() []*baremetal.BaremetalStorage {
|
||||
return a.devs
|
||||
}
|
||||
|
||||
func (a *MdadmRaidAdapter) setDevices(devs []*baremetal.BaremetalStorage) {
|
||||
a.devs = devs
|
||||
}
|
||||
|
||||
func (a *MdadmRaidAdapter) BuildRaid0(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return a.buildRaid("0", devs, conf)
|
||||
}
|
||||
|
||||
func (a *MdadmRaidAdapter) BuildRaid1(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return a.buildRaid("1", devs, conf)
|
||||
}
|
||||
|
||||
func (a *MdadmRaidAdapter) BuildRaid5(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return a.buildRaid("5", devs, conf)
|
||||
}
|
||||
|
||||
func (a *MdadmRaidAdapter) BuildRaid10(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return a.buildRaid("10", devs, conf)
|
||||
}
|
||||
|
||||
func (a *MdadmRaidAdapter) BuildNoneRaid(devs []*baremetal.BaremetalStorage) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *MdadmRaidAdapter) PostBuildRaid() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *MdadmRaidAdapter) buildRaid(level string, devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
if len(devs) == 0 {
|
||||
return fmt.Errorf("no devices provided for RAID %s", level)
|
||||
}
|
||||
|
||||
var mdNum int
|
||||
var err error
|
||||
if conf.SoftRaidIdx != nil {
|
||||
mdNum = *conf.SoftRaidIdx
|
||||
} else {
|
||||
mdNum, err = a.getNextMdNum()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get next md number")
|
||||
}
|
||||
}
|
||||
|
||||
devPaths := make([]string, 0, len(devs))
|
||||
for _, dev := range devs {
|
||||
if dev.Dev == "" {
|
||||
return fmt.Errorf("device path is empty for storage")
|
||||
}
|
||||
devPaths = append(devPaths, path.Join("/dev", dev.Dev))
|
||||
}
|
||||
|
||||
for _, dev := range devPaths {
|
||||
if err := a.ensureDeviceClean(dev); err != nil {
|
||||
return errors.Wrapf(err, "clean device %s", dev)
|
||||
}
|
||||
}
|
||||
|
||||
mdDev := fmt.Sprintf("/dev/md/md%d", mdNum)
|
||||
|
||||
imsmDev := fmt.Sprintf("/dev/md/imsm%d", mdNum)
|
||||
cmdImsm := fmt.Sprintf("%s --create %s --metadata=imsm --raid-devices=%d --run --force %s", MDADM_BIN, imsmDev, len(devs), strings.Join(devPaths, " "))
|
||||
output, err := a.term.Run(cmdImsm)
|
||||
if err != nil {
|
||||
log.Errorf("mdadm create imsm raid %s failed, output: %v %s", level, output, err)
|
||||
} else {
|
||||
a.term.Run(fmt.Sprintf("%s --wait %s", MDADM_BIN, imsmDev))
|
||||
time.Sleep(time.Second * 3)
|
||||
}
|
||||
|
||||
args := []string{
|
||||
"--create",
|
||||
mdDev,
|
||||
fmt.Sprintf("--level=%s", level),
|
||||
fmt.Sprintf("--raid-devices=%d", len(devs)),
|
||||
"--force",
|
||||
"--run",
|
||||
}
|
||||
|
||||
for _, dev := range devPaths {
|
||||
args = append(args, dev)
|
||||
}
|
||||
|
||||
args = append(args, "--assume-clean")
|
||||
|
||||
cmd := fmt.Sprintf("%s %s", MDADM_BIN, strings.Join(args, " "))
|
||||
log.Infof("Building software RAID %s: %s", level, cmd)
|
||||
|
||||
output, err = a.term.Run(cmd)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "mdadm create raid %s failed, output: %v", level, output)
|
||||
}
|
||||
|
||||
cmd = fmt.Sprintf("%s --wait %s", MDADM_BIN, mdDev)
|
||||
output, err = a.term.Run(cmd)
|
||||
if err != nil {
|
||||
log.Errorf("mdadm wait raid %s failed: %s", mdDev, output)
|
||||
//return errors.Wrapf(err, "mdadm wait raid %s failed, output: %v", mdDev, output)
|
||||
}
|
||||
|
||||
log.Infof("Successfully created software RAID %s: /dev/md/md%d, start sync block devs", level, mdNum)
|
||||
|
||||
for i := range devPaths {
|
||||
flushCmd := fmt.Sprintf("blockdev --flushbufs %s", devPaths[i])
|
||||
output, err = a.term.Run(flushCmd)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "mdadm blockdev flushbufs %s failed, output: %v", devPaths[i], output)
|
||||
}
|
||||
}
|
||||
|
||||
output, err = a.term.Run("sync")
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "mdadm %s sync failed, output: %v", mdDev, output)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *MdadmRaidAdapter) getNextMdNum() (int, error) {
|
||||
cmd := "ls -1 /dev/md/ 2>/dev/null | grep -E '/dev/md/md[0-9]+$' || true"
|
||||
output, err := a.term.Run(cmd)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "list md devices")
|
||||
}
|
||||
|
||||
usedNums := make(map[int]bool)
|
||||
mdNumRe := regexp.MustCompile(`/dev/md/md(\d+)`)
|
||||
for _, line := range output {
|
||||
matches := mdNumRe.FindStringSubmatch(line)
|
||||
if len(matches) > 1 {
|
||||
if num, err := strconv.Atoi(matches[1]); err == nil {
|
||||
usedNums[num] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < 256; i++ {
|
||||
if !usedNums[i] {
|
||||
return i, nil
|
||||
}
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf("no available md device number")
|
||||
}
|
||||
|
||||
func (a *MdadmRaidAdapter) ensureDeviceClean(dev string) error {
|
||||
cmd := fmt.Sprintf("%s --examine %s 2>/dev/null || true", MDADM_BIN, dev)
|
||||
output, err := a.term.Run(cmd)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "examine device %s", dev)
|
||||
}
|
||||
|
||||
for _, line := range output {
|
||||
if strings.Contains(line, "mdadm") || strings.Contains(line, "ARRAY") {
|
||||
cmd := fmt.Sprintf("%s --zero-superblock --force %s", MDADM_BIN, dev)
|
||||
_, err := a.term.Run(cmd)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "zero superblock on %s", dev)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -39,29 +39,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/util/dbutils"
|
||||
)
|
||||
|
||||
func InitDB(options *common_options.DBOptions) {
|
||||
if options.DebugSqlchemy {
|
||||
log.Warningf("debug Sqlchemy is turned on")
|
||||
sqlchemy.DEBUG_SQLCHEMY = true
|
||||
}
|
||||
|
||||
log.Infof("Registered SQL drivers: %s", strings.Join(sql.Drivers(), ", "))
|
||||
|
||||
consts.QueryOffsetOptimization = options.QueryOffsetOptimization
|
||||
|
||||
if options.HistoricalUniqueName {
|
||||
consts.EnableHistoricalUniqueName()
|
||||
} else {
|
||||
consts.DisableHistoricalUniqueName()
|
||||
}
|
||||
|
||||
if options.OpsLogMaxKeepMonths > 0 {
|
||||
consts.SetSplitableMaxKeepMonths(options.OpsLogMaxKeepMonths)
|
||||
}
|
||||
if options.SplitableMaxDurationHours > 0 {
|
||||
consts.SetSplitableMaxDurationHours(options.SplitableMaxDurationHours)
|
||||
}
|
||||
|
||||
func InitDBConn(options *common_options.DBOptions) {
|
||||
dialect, sqlStr, err := options.GetDBConnection()
|
||||
if err != nil {
|
||||
log.Fatalf("Invalid SqlConnection string: %s error: %v", options.SqlConnection, err)
|
||||
@@ -103,8 +81,10 @@ func InitDB(options *common_options.DBOptions) {
|
||||
dbConn.SetConnMaxLifetime(time.Duration(options.DbMaxWaitTimeoutSeconds) * time.Second)
|
||||
// ConnMaxIdleTime should be half of ConnMaxLifetime
|
||||
dbConn.SetConnMaxIdleTime(time.Duration(options.DbMaxWaitTimeoutSeconds/2) * time.Second)
|
||||
}
|
||||
|
||||
dialect, sqlStr, err = options.GetClickhouseConnStr()
|
||||
func InitClickhouseConn(options *common_options.DBOptions) {
|
||||
dialect, sqlStr, err := options.GetClickhouseConnStr()
|
||||
if err == nil {
|
||||
// connect to clickcloud
|
||||
// force convert sqlstr from clickhouse v2 to v1
|
||||
@@ -126,6 +106,33 @@ func InitDB(options *common_options.DBOptions) {
|
||||
consts.OpsLogWithClickhouse = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func InitDB(options *common_options.DBOptions) {
|
||||
if options.DebugSqlchemy {
|
||||
log.Warningf("debug Sqlchemy is turned on")
|
||||
sqlchemy.DEBUG_SQLCHEMY = true
|
||||
}
|
||||
|
||||
log.Infof("Registered SQL drivers: %s", strings.Join(sql.Drivers(), ", "))
|
||||
|
||||
consts.QueryOffsetOptimization = options.QueryOffsetOptimization
|
||||
|
||||
if options.HistoricalUniqueName {
|
||||
consts.EnableHistoricalUniqueName()
|
||||
} else {
|
||||
consts.DisableHistoricalUniqueName()
|
||||
}
|
||||
|
||||
if options.OpsLogMaxKeepMonths > 0 {
|
||||
consts.SetSplitableMaxKeepMonths(options.OpsLogMaxKeepMonths)
|
||||
}
|
||||
if options.SplitableMaxDurationHours > 0 {
|
||||
consts.SetSplitableMaxDurationHours(options.SplitableMaxDurationHours)
|
||||
}
|
||||
|
||||
InitDBConn(options)
|
||||
InitClickhouseConn(options)
|
||||
|
||||
switch options.LockmanMethod {
|
||||
case common_options.LockMethodInMemory, "":
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
modules "yunion.io/x/onecloud/pkg/mcclient/modules/identity"
|
||||
"yunion.io/x/onecloud/pkg/util/ctx"
|
||||
)
|
||||
|
||||
type domainCacheSyncWorker struct {
|
||||
@@ -35,7 +36,7 @@ type domainCacheSyncWorker struct {
|
||||
|
||||
func (w *domainCacheSyncWorker) Run() {
|
||||
log.Debugf("[domainCacheSyncWorker] Run domain cache sync worker ...")
|
||||
err := syncDomains(context.Background(), w.ids)
|
||||
err := syncDomains(ctx.CtxWithTime(), w.ids)
|
||||
if err != nil {
|
||||
log.Errorf("fail to syncDomains %s", err)
|
||||
}
|
||||
|
||||
@@ -1085,12 +1085,15 @@ func (dispatcher *DBModelDispatcher) GetSpecific(ctx context.Context, idStr stri
|
||||
|
||||
funcName := fmt.Sprintf("GetDetails%s", specCamel)
|
||||
funcValue := modelValue.MethodByName(funcName)
|
||||
log.Errorf("MethodByName %s", funcName)
|
||||
if !funcValue.IsValid() || funcValue.IsNil() {
|
||||
log.Errorf("MethodByName2 %s", funcName)
|
||||
return nil, httperrors.NewSpecNotFoundError("%s %s %s not found", dispatcher.Keyword(), idStr, spec)
|
||||
}
|
||||
|
||||
outs, err := callFunc(funcValue, funcName, params...)
|
||||
if err != nil {
|
||||
log.Errorf("MethodByName4 %s", funcName)
|
||||
return nil, err
|
||||
}
|
||||
if len(outs) != 2 {
|
||||
@@ -1100,6 +1103,7 @@ func (dispatcher *DBModelDispatcher) GetSpecific(ctx context.Context, idStr stri
|
||||
resVal := outs[0]
|
||||
errVal := outs[1].Interface()
|
||||
if !gotypes.IsNil(errVal) {
|
||||
log.Errorf("MethodByName3 %s", funcName)
|
||||
return nil, errVal.(error)
|
||||
} else {
|
||||
if gotypes.IsNil(resVal.Interface()) {
|
||||
@@ -1848,6 +1852,10 @@ func updateItem(manager IModelManager, item IModel, ctx context.Context, userCre
|
||||
|
||||
item.PostUpdate(ctx, userCred, query, data)
|
||||
|
||||
if err := manager.GetExtraHook().AfterPostUpdate(ctx, userCred, item, query, data); err != nil {
|
||||
logclient.AddActionLogWithContext(ctx, item, logclient.ACT_POST_UPDATE_HOOK, err, userCred, false)
|
||||
}
|
||||
|
||||
return getItemDetails(manager, item, ctx, userCred, query)
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/policy"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type DBJointModelDispatcher struct {
|
||||
@@ -210,6 +211,9 @@ func attachItems(
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
item.PostCreate(ctx, userCred, nil, query, data)
|
||||
if err := dispatcher.JointModelManager().GetExtraHook().AfterPostCreate(ctx, userCred, item.GetOwnerId(), item, query, data); err != nil {
|
||||
logclient.AddActionLogWithContext(ctx, item, logclient.ACT_POST_CREATE_HOOK, err, userCred, false)
|
||||
}
|
||||
OpsLog.LogAttachEvent(ctx, master, slave, userCred, jsonutils.Marshal(item))
|
||||
dispatcher.manager.OnCreateComplete(ctx, []IModel{item}, userCred, nil, query, []jsonutils.JSONObject{data})
|
||||
|
||||
@@ -322,5 +326,8 @@ func DetachJoint(ctx context.Context, userCred mcclient.TokenCredential, item IJ
|
||||
if err == nil {
|
||||
OpsLog.LogDetachEvent(ctx, JointMaster(item), JointSlave(item), userCred, item.GetShortDesc(ctx))
|
||||
}
|
||||
if err := item.GetModelManager().GetExtraHook().AfterPostDelete(ctx, userCred, item, nil); err != nil {
|
||||
logclient.AddActionLogWithContext(ctx, item, logclient.ACT_POST_DELETE_HOOK, err, userCred, false)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
71
pkg/cloudcommon/db/history_data_clean.go
Normal file
71
pkg/cloudcommon/db/history_data_clean.go
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/gotypes"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/appsrv"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
)
|
||||
|
||||
func AddHistoryDataCleanHandler(prefix string, app *appsrv.Application) {
|
||||
prefix = fmt.Sprintf("%s/history-data-clean", prefix)
|
||||
app.AddHandler2("POST", prefix, auth.Authenticate(historyDataCleanHandler), nil, "history_data_clean", nil)
|
||||
}
|
||||
|
||||
func historyDataCleanHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
||||
userCred := fetchUserCredential(ctx)
|
||||
if !userCred.HasSystemAdminPrivilege() {
|
||||
httperrors.ForbiddenError(ctx, w, "only sysadmin can clean history data")
|
||||
return
|
||||
}
|
||||
input, err := appsrv.FetchJSON(r)
|
||||
if err != nil {
|
||||
httperrors.InputParameterError(ctx, w, "FetchJSON")
|
||||
return
|
||||
}
|
||||
date := time.Now().AddDate(0, -1, 0)
|
||||
if !gotypes.IsNil(input) && input.Contains("day") {
|
||||
day, _ := input.Int("day")
|
||||
date = time.Now().AddDate(0, 0, int(day)*-1)
|
||||
}
|
||||
go func() {
|
||||
for _, manager := range globalTables {
|
||||
if hM, ok := manager.(IHistoryDataManager); ok {
|
||||
start := time.Now()
|
||||
cnt, err := hM.HistoryDataClean(ctx, date)
|
||||
if err != nil {
|
||||
log.Errorf("clean %s data error: %v", manager.Keyword(), err)
|
||||
continue
|
||||
}
|
||||
log.Debugf("clean %d %s history data cost %s", cnt, manager.Keyword(), time.Now().Sub(start).Round(time.Second))
|
||||
}
|
||||
}
|
||||
}()
|
||||
appsrv.SendJSON(w, jsonutils.Marshal(map[string]string{"status": "ok"}))
|
||||
}
|
||||
|
||||
type IHistoryDataManager interface {
|
||||
HistoryDataClean(ctx context.Context, timeBefor time.Time) (int, error)
|
||||
}
|
||||
@@ -152,6 +152,7 @@ type IModelManager interface {
|
||||
|
||||
type IModelManagerExtraHook interface {
|
||||
AfterPostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, model IModel, query jsonutils.JSONObject, data jsonutils.JSONObject) error
|
||||
AfterPostUpdate(ctx context.Context, userCred mcclient.TokenCredential, model IModel, query jsonutils.JSONObject, data jsonutils.JSONObject) error
|
||||
AfterPostDelete(ctx context.Context, userCred mcclient.TokenCredential, model IModel, query jsonutils.JSONObject) error
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,11 @@ package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
@@ -27,6 +30,7 @@ import (
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
@@ -255,3 +259,67 @@ func (model *SJointResourceBase) ValidateUpdateData(
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (manager *SJointResourceBaseManager) HistoryDataClean(ctx context.Context, timeBefor time.Time) (int, error) {
|
||||
q := manager.RawQuery("row_id").IsTrue("deleted").LE("deleted_at", timeBefor)
|
||||
rows, err := q.Rows()
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return 0, nil
|
||||
}
|
||||
return 0, errors.Wrap(err, "Query")
|
||||
}
|
||||
defer rows.Close()
|
||||
ids := []string{}
|
||||
for rows.Next() {
|
||||
var id string
|
||||
err := rows.Scan(&id)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "rows.Scan")
|
||||
}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
var purge = func(ids []string) error {
|
||||
vars := []interface{}{}
|
||||
placeholders := make([]string, len(ids))
|
||||
for i := range placeholders {
|
||||
placeholders[i] = "?"
|
||||
vars = append(vars, ids[i])
|
||||
}
|
||||
placeholder := strings.Join(placeholders, ",")
|
||||
sql := fmt.Sprintf(
|
||||
"delete from %s where row_id in (%s)",
|
||||
manager.TableSpec().Name(), placeholder,
|
||||
)
|
||||
lockman.LockRawObject(ctx, manager.Keyword(), "purge")
|
||||
defer lockman.ReleaseRawObject(ctx, manager.Keyword(), "purge")
|
||||
|
||||
_, err = sqlchemy.GetDB().Exec(
|
||||
sql, vars...,
|
||||
)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, strings.ReplaceAll(sql, "?", "%s"), vars...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var splitByLen = func(data []string, splitLen int) [][]string {
|
||||
var result [][]string
|
||||
for i := 0; i < len(data); i += splitLen {
|
||||
end := i + splitLen
|
||||
if end > len(data) {
|
||||
end = len(data)
|
||||
}
|
||||
result = append(result, data[i:end])
|
||||
}
|
||||
return result
|
||||
}
|
||||
idsArr := splitByLen(ids, 100)
|
||||
for i := range idsArr {
|
||||
err = purge(idsArr[i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
return len(ids), nil
|
||||
}
|
||||
|
||||
@@ -344,6 +344,9 @@ func (manager *SMetadataManager) metadataBaseFilter(q *sqlchemy.SQuery, input ap
|
||||
if len(input.KeyLike) > 0 {
|
||||
q = q.Contains("key", input.KeyLike)
|
||||
}
|
||||
if len(input.ValueLike) > 0 {
|
||||
q = q.Contains("value", input.ValueLike)
|
||||
}
|
||||
if len(input.Key) > 0 {
|
||||
q = q.In("key", input.Key)
|
||||
}
|
||||
|
||||
@@ -880,3 +880,7 @@ func (e SEmptyExtraHook) AfterPostCreate(ctx context.Context, userCred mcclient.
|
||||
func (e SEmptyExtraHook) AfterPostDelete(ctx context.Context, userCred mcclient.TokenCredential, model IModel, query jsonutils.JSONObject) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e SEmptyExtraHook) AfterPostUpdate(ctx context.Context, userCred mcclient.TokenCredential, model IModel, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user