mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/yunionio/cloudpods.git
synced 2026-09-20 16:13:56 +08:00
Compare commits
223 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0bece9d948 | ||
|
|
14dcb91758 | ||
|
|
3d869c69bb | ||
|
|
09ef280e33 | ||
|
|
4332008c3f | ||
|
|
73c0f0350f | ||
|
|
48a894efdf | ||
|
|
fc274d5da6 | ||
|
|
e39015fa45 | ||
|
|
1bb9801666 | ||
|
|
c22c4f8ef6 | ||
|
|
5584e9af1a | ||
|
|
44e360dcdd | ||
|
|
a216ef28dd | ||
|
|
3b12892172 | ||
|
|
704cce8392 | ||
|
|
2fc04497b2 | ||
|
|
bd64be4d8a | ||
|
|
8dd1a897fc | ||
|
|
57eef5ede6 | ||
|
|
ff7fa0a520 | ||
|
|
0994e8c1ea | ||
|
|
d7dc89ccb3 | ||
|
|
8610731af3 | ||
|
|
3cc72fac65 | ||
|
|
f7e8c20f43 | ||
|
|
dbf8fde45b | ||
|
|
a6a3332e64 | ||
|
|
ca55fbd641 | ||
|
|
4ee32ef454 | ||
|
|
eeb2fcfbc8 | ||
|
|
8612095454 | ||
|
|
7612f85c6a | ||
|
|
c09c5cac79 | ||
|
|
50473268f9 | ||
|
|
010ed4f9ad | ||
|
|
eefe0aa8cb | ||
|
|
a11e5d14de | ||
|
|
a1eed47e66 | ||
|
|
50fe044cfc | ||
|
|
cdb97511c3 | ||
|
|
6be7e015d3 | ||
|
|
0eef67fafb | ||
|
|
bbb538b93d | ||
|
|
4acb2757a9 | ||
|
|
d85883780d | ||
|
|
e76abe883b | ||
|
|
a82f00aae7 | ||
|
|
1bfa27bc49 | ||
|
|
ec688fd206 | ||
|
|
20f55fe992 | ||
|
|
1fe7a54218 | ||
|
|
24bf2a163a | ||
|
|
ea4505ae55 | ||
|
|
3bcb337a4b | ||
|
|
7ee2026b21 | ||
|
|
ebe79b12d1 | ||
|
|
650ccdd7c7 | ||
|
|
68e006b71c | ||
|
|
57efd8a86b | ||
|
|
3aa83bb86d | ||
|
|
de926037dc | ||
|
|
df4f30ac47 | ||
|
|
96e443f90b | ||
|
|
dfa4d87702 | ||
|
|
4e199b84eb | ||
|
|
c17fe2df22 | ||
|
|
754d046d3a | ||
|
|
20380ae9e6 | ||
|
|
47d38a253a | ||
|
|
d366048e51 | ||
|
|
410fd2936f | ||
|
|
90e10db57c | ||
|
|
9975543ddb | ||
|
|
0c658ec53f | ||
|
|
58fb3fc9e2 | ||
|
|
f74635f3da | ||
|
|
f4972c22ba | ||
|
|
6f2bdfa22f | ||
|
|
e3d3c1f029 | ||
|
|
2fd40396c4 | ||
|
|
f416fe126c | ||
|
|
cb7956f1f1 | ||
|
|
8ca6cfa3d3 | ||
|
|
e467ef6ec7 | ||
|
|
861cd47e62 | ||
|
|
d515e5e32c | ||
|
|
71c0cc65ee | ||
|
|
86896da1f6 | ||
|
|
67082f32d3 | ||
|
|
b96b2f0b53 | ||
|
|
a8a2a248df | ||
|
|
3997f6fbe6 | ||
|
|
05efb17d35 | ||
|
|
2af9104d96 | ||
|
|
a0d99cf879 | ||
|
|
a8d550d4d8 | ||
|
|
5ccece54ac | ||
|
|
180b122167 | ||
|
|
78ba5e2fd8 | ||
|
|
9f5256c344 | ||
|
|
cdd032c711 | ||
|
|
81133a53a2 | ||
|
|
c6893892d9 | ||
|
|
8a9f3e09ea | ||
|
|
606b241b0d | ||
|
|
178a7071f0 | ||
|
|
27e5ff8635 | ||
|
|
5dc1486e7f | ||
|
|
6a50fce0ab | ||
|
|
132a00d8e0 | ||
|
|
fed6395132 | ||
|
|
7c87d73d95 | ||
|
|
a73c3c8d0e | ||
|
|
f3a567f630 | ||
|
|
5160669550 | ||
|
|
e1c5ebc29c | ||
|
|
de1553770c | ||
|
|
928c0602dd | ||
|
|
6cc34c6fb1 | ||
|
|
4885025618 | ||
|
|
68ebbbcbcc | ||
|
|
040a45aa46 | ||
|
|
299d3bed6e | ||
|
|
c4c302236f | ||
|
|
88bcb82197 | ||
|
|
80a9ed9a79 | ||
|
|
f4f973429d | ||
|
|
863a28f294 | ||
|
|
8858e7913c | ||
|
|
6254b64d5d | ||
|
|
43f8ac0027 | ||
|
|
36bd1baafe | ||
|
|
98ca80e630 | ||
|
|
a2613e6bce | ||
|
|
a8b14bb739 | ||
|
|
4850c4f8e2 | ||
|
|
64dec4254f | ||
|
|
ada90754f9 | ||
|
|
fb3456c42d | ||
|
|
cefbeb7a14 | ||
|
|
1fc01ebe94 | ||
|
|
ff0606f166 | ||
|
|
83dd534241 | ||
|
|
a7771885cf | ||
|
|
88fa743e4e | ||
|
|
0e917bb275 | ||
|
|
cd76ce27c3 | ||
|
|
114de75e7e | ||
|
|
047509ebb8 | ||
|
|
71e79e5a7b | ||
|
|
4c62508b01 | ||
|
|
e5b637906c | ||
|
|
dd7d34402f | ||
|
|
157bfb696b | ||
|
|
464e0450f9 | ||
|
|
a4b5562bd0 | ||
|
|
f0354d0c9b | ||
|
|
c3c3c00759 | ||
|
|
83adeaae4e | ||
|
|
d7f05e983f | ||
|
|
5d075bbaaf | ||
|
|
86fda0f7d0 | ||
|
|
53c8c16052 | ||
|
|
46ba9cd424 | ||
|
|
ee59f2a410 | ||
|
|
5cfbb416b3 | ||
|
|
a711f832e6 | ||
|
|
f31216be0e | ||
|
|
bc0106902a | ||
|
|
2dbfc80fac | ||
|
|
4fa95bf608 | ||
|
|
af0813cd09 | ||
|
|
3b5602e1ea | ||
|
|
e4f7d3233c | ||
|
|
287f98ac86 | ||
|
|
bb44f1cdfb | ||
|
|
644ab6f925 | ||
|
|
e775e798aa | ||
|
|
331d9d2a67 | ||
|
|
d5ed96a651 | ||
|
|
4ce85f310b | ||
|
|
3f6e669324 | ||
|
|
3f4b2163f3 | ||
|
|
78b6f85662 | ||
|
|
3124113e2f | ||
|
|
38b34239cd | ||
|
|
370b35852c | ||
|
|
f7c8bbc00b | ||
|
|
f64c6c54da | ||
|
|
c4db4bc43e | ||
|
|
1afe6ef41b | ||
|
|
83896cdcc3 | ||
|
|
38914b967d | ||
|
|
7695eb905c | ||
|
|
562aefda85 | ||
|
|
0143d271e1 | ||
|
|
de2b95cab7 | ||
|
|
fc5a78c7e3 | ||
|
|
3986dbc434 | ||
|
|
192e03fcd7 | ||
|
|
44db018039 | ||
|
|
6751d1d3af | ||
|
|
5ea100865d | ||
|
|
987b641bd0 | ||
|
|
77e56db095 | ||
|
|
b7629422f7 | ||
|
|
589daf5063 | ||
|
|
a066301ae2 | ||
|
|
7d07b4aa5f | ||
|
|
b96f225274 | ||
|
|
40c8b54cba | ||
|
|
93879980f5 | ||
|
|
5bb13e48b7 | ||
|
|
64fcdea2b0 | ||
|
|
57fa6361fc | ||
|
|
732159137b | ||
|
|
d2ec564ccc | ||
|
|
a4323eab43 | ||
|
|
7335875ef1 | ||
|
|
8d98218f06 | ||
|
|
af274d7ad2 | ||
|
|
25baa6f509 |
8
Makefile
8
Makefile
@@ -6,6 +6,7 @@ ROOT_DIR := $(CURDIR)
|
||||
BUILD_DIR := $(ROOT_DIR)/_output
|
||||
BIN_DIR := $(BUILD_DIR)/bin
|
||||
BUILD_SCRIPT := $(ROOT_DIR)/build/build.sh
|
||||
DEB_BUILD_SCRIPT := $(ROOT_DIR)/build/build_deb.sh
|
||||
|
||||
ifeq ($(ONECLOUD_CI_BUILD),)
|
||||
GIT_COMMIT := $(shell git rev-parse --short HEAD)
|
||||
@@ -64,6 +65,7 @@ endif
|
||||
|
||||
cmdTargets:=$(filter-out cmd/host-image,$(wildcard cmd/*))
|
||||
rpmTargets:=$(foreach b,$(patsubst cmd/%,%,$(cmdTargets)),$(if $(shell [ -f "$(CURDIR)/build/$(b)/vars" ] && echo 1),rpm/$(b)))
|
||||
debTargets:=$(foreach b,$(patsubst cmd/%,%,$(cmdTargets)),$(if $(shell [ -f "$(CURDIR)/build/$(b)/vars" ] && echo 1),deb/$(b)))
|
||||
|
||||
all: build
|
||||
|
||||
@@ -93,6 +95,9 @@ cmd/%: prepare_dir
|
||||
rpm/%: cmd/%
|
||||
$(BUILD_SCRIPT) $*
|
||||
|
||||
deb/%: cmd/%
|
||||
$(DEB_BUILD_SCRIPT) $*
|
||||
|
||||
pkg/%: prepare_dir
|
||||
$(GO_INSTALL) $(REPO_PREFIX)/$@
|
||||
|
||||
@@ -102,6 +107,9 @@ build:
|
||||
rpm:
|
||||
$(MAKE) $(rpmTargets)
|
||||
|
||||
deb:
|
||||
$(MAKE) $(debTargets)
|
||||
|
||||
rpmclean:
|
||||
rm -fr $(BUILD_DIR)/rpms
|
||||
|
||||
|
||||
76
build/build_deb.sh
Executable file
76
build/build_deb.sh
Executable file
@@ -0,0 +1,76 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ -z "$ROOT_DIR" ]; then
|
||||
pushd $(dirname $(readlink -f "$BASH_SOURCE")) > /dev/null
|
||||
ROOT_DIR=$(cd .. && pwd)
|
||||
popd > /dev/null
|
||||
fi
|
||||
|
||||
SRC_BIN=$ROOT_DIR/_output/bin
|
||||
SRC_BUILD=$ROOT_DIR/build
|
||||
OUTPUT_DIR=$ROOT_DIR/_output/debs
|
||||
|
||||
PKG=$1
|
||||
BIN_PATH=${2:-/opt/yunion/bin}
|
||||
|
||||
if [ -z "$PKG" ]; then
|
||||
echo "Usage: $0 <package>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BIN="$SRC_BIN/$PKG"
|
||||
ROOT="$SRC_BUILD/$PKG"
|
||||
|
||||
if [ ! -x "$BIN" ]; then
|
||||
echo "$BIN not exists"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -x "$ROOT" ]; then
|
||||
echo "$ROOT not exists"
|
||||
exit 1
|
||||
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
|
||||
cp -rf $ROOT/root/* $BUILDROOT/
|
||||
|
||||
|
||||
echo "Build root ${BUILDROOT}"
|
||||
|
||||
case $(uname -m) in
|
||||
x86_64)
|
||||
CURRENT_ARCH=amd64
|
||||
;;
|
||||
aarch64)
|
||||
CURRENT_ARCH=arm64
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "Package: yunion-$1
|
||||
Version: $FULL_VERSION
|
||||
Section: base
|
||||
Priority: optional
|
||||
Architecture: $CURRENT_ARCH
|
||||
Maintainer: wanyaoqi@yunionyun.com
|
||||
Description: Yunion $1
|
||||
" > $BUILDROOT/DEBIAN/control
|
||||
chmod 0755 $BUILDROOT/DEBIAN/control
|
||||
|
||||
|
||||
dpkg-deb --build $BUILDROOT
|
||||
@@ -47,7 +47,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding-bottom: 10px;">您正在验证邮箱,请在验证码输入框中输入:{{.code}},已完成验证。</td>
|
||||
<td style="padding-bottom: 10px;">您正在验证邮箱,请在验证码输入框中输入:{{.code}},以完成验证。</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
@@ -0,0 +1 @@
|
||||
{{.os_type}} image {{.name}} upload completed
|
||||
@@ -0,0 +1,66 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
<table style="width: 650px; margin-bottom: 20px;" border="0" cellpadding="0" cellspacing="0" align="center">
|
||||
<tr style="height: 50px; background: #333; overflow: hidden;">
|
||||
<td>
|
||||
<table style="margin-left: 20px;">
|
||||
<tr>
|
||||
<td>
|
||||
<img src="data:{{.login_logo_format}};base64,{{.login_logo}}" alt="" style="color: #fff; height: 32px; vertical-align: middle;">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td>
|
||||
<table style="float: right;">
|
||||
<tr>
|
||||
<td style="padding-left: 20px; padding-right: 20px;">
|
||||
<a href="" style="text-decoration: none; color: #20A0FF; font-size: 12px; display: none;">Product</a>
|
||||
</td>
|
||||
<td style="padding-left: 20px; padding-right: 20px;">
|
||||
<a href="" style="text-decoration: none; color: #20A0FF; font-size: 12px; display: none;">Solution</a>
|
||||
</td>
|
||||
<td style="padding-left: 20px; padding-right: 20px;">
|
||||
<a href="" style="text-decoration: none; color: #20A0FF; font-size: 12px; display: none;">Service</a>
|
||||
</td>
|
||||
<td style="padding-left: 20px; padding-right: 20px;">
|
||||
<a href="" style="text-decoration: none; color: #20A0FF; font-size: 12px; display: none;">Help and Documentation</a>
|
||||
</td>
|
||||
<td style="padding-left: 20px; padding-right: 20px;">
|
||||
<a href="" style="text-decoration: none; color: #20A0FF; font-size: 12px; display: none;">About</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 100%;" colspan="2">
|
||||
<table style="padding: 20px 10px; width: 100%;">
|
||||
<tr>
|
||||
<td style="padding-bottom: 13px;">
|
||||
Dear {{.name}}:
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding-bottom: 13px;">You are verifying your email, please enter the following code on the email verification page:</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding-bottom: 10px; font-size: large">{{.code}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="width: 96%;">
|
||||
<td colspan="2" style="border-top: 1px dashed #ccc; color: #333; font-size: 12px; padding-bottom: 10px; font-weight: 100;">If you are not operating by yourself, please log in to the platform in time and change your password to ensure the security of your account.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" style="background: #333; text-align: right; padding-right: 20px; font-size: 12px; color: #fff; height: 50px;">Copyrights © {{.copyright}}. All rights reserved.</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
Image {{.name}} upload completed
|
||||
@@ -0,0 +1 @@
|
||||
{{.copyright}} Verify
|
||||
@@ -34,6 +34,7 @@ import (
|
||||
_ "yunion.io/x/onecloud/cmd/climc/shell/monitor"
|
||||
_ "yunion.io/x/onecloud/cmd/climc/shell/notifyv2"
|
||||
_ "yunion.io/x/onecloud/cmd/climc/shell/servicetree"
|
||||
_ "yunion.io/x/onecloud/cmd/climc/shell/suggestion"
|
||||
_ "yunion.io/x/onecloud/cmd/climc/shell/yunionconf"
|
||||
)
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ func init() {
|
||||
Disabled bool `help:"Show disabled host only" json:"-"`
|
||||
HostType string `help:"Host type filter" choices:"baremetal|hypervisor|esxi|kubelet|hyperv|aliyun|azure|qcloud|aws|huawei|ucloud|google|ctyun"`
|
||||
AnyMac string `help:"Mac matches one of the host's interface"`
|
||||
AnyIp string `help:"IP matches one of the host's interface"`
|
||||
|
||||
IsBaremetal *bool `help:"filter host list by is_baremetal=true|false"`
|
||||
|
||||
@@ -407,12 +408,14 @@ func init() {
|
||||
})
|
||||
|
||||
type HostAddNetIfOptions struct {
|
||||
ID string `help:"ID or Name of host"`
|
||||
WIRE string `help:"ID or Name of wire to attach"`
|
||||
MAC string `help:"Mac address of NIC"`
|
||||
INDEX int64 `help:"nic index"`
|
||||
Type string `help:"Nic type" choices:"admin|ipmi"`
|
||||
IpAddr string `help:"IP address"`
|
||||
ID string `help:"ID or Name of host"`
|
||||
WIRE string `help:"ID or Name of wire to attach"`
|
||||
MAC string `help:"Mac address of NIC"`
|
||||
INDEX int64 `help:"nic index"`
|
||||
Type string `help:"Nic type" choices:"admin|ipmi"`
|
||||
IpAddr string `help:"IP address"`
|
||||
Bridge string `help:"Bridge of hostwire"`
|
||||
Interface string `help:"Interface name, eg:eth0, en0"`
|
||||
}
|
||||
R(&HostAddNetIfOptions{}, "host-add-netif", "Host add a NIC", func(s *mcclient.ClientSession, args *HostAddNetIfOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
@@ -426,6 +429,12 @@ func init() {
|
||||
if len(args.IpAddr) > 0 {
|
||||
params.Add(jsonutils.NewString(args.IpAddr), "ip_addr")
|
||||
}
|
||||
if len(args.Bridge) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Bridge), "bridge")
|
||||
}
|
||||
if len(args.Interface) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Interface), "interface")
|
||||
}
|
||||
result, err := modules.Hosts.PerformAction(s, args.ID, "add-netif", params)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -15,142 +15,17 @@
|
||||
package compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/compute"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type SecGroupRulesListOptions struct {
|
||||
options.BaseListOptions
|
||||
Secgroup string `help:"Secgroup ID or Name"`
|
||||
SecgroupName string `help:"Search rules by fuzzy secgroup name"`
|
||||
Projects []string `help:"Filter rules by project"`
|
||||
Direction string `help:"filter Direction of rule" choices:"in|out"`
|
||||
Protocol string `help:"filter Protocol of rule" choices:"any|tcp|udp|icmp"`
|
||||
Action string `help:"filter Actin of rule" choices:"allow|deny"`
|
||||
Ports string `help:"filter Ports of rule"`
|
||||
Ip string `help:"filter cidr of rule"`
|
||||
}
|
||||
|
||||
R(&SecGroupRulesListOptions{}, "secgroup-rule-list", "List all security group", func(s *mcclient.ClientSession, args *SecGroupRulesListOptions) error {
|
||||
params, err := options.ListStructToParams(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := modules.SecGroupRules.List(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result, modules.SecGroupRules.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
|
||||
type SecGroupRuleDetailOptions struct {
|
||||
ID string `help:"ID or Name of security group rule"`
|
||||
}
|
||||
R(&SecGroupRuleDetailOptions{}, "secgroup-rule-show", "Show details of rule", func(s *mcclient.ClientSession, args *SecGroupRuleDetailOptions) error {
|
||||
if rule, e := modules.SecGroupRules.Get(s, args.ID, nil); e != nil {
|
||||
return e
|
||||
} else {
|
||||
printObject(rule)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&SecGroupRuleDetailOptions{}, "secgroup-rule-delete", "Delete a secgroup rule", func(s *mcclient.ClientSession, args *SecGroupRuleDetailOptions) error {
|
||||
if rule, e := modules.SecGroupRules.Delete(s, args.ID, nil); e != nil {
|
||||
return e
|
||||
} else {
|
||||
printObject(rule)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
type SecGroupRulesCreateOptions struct {
|
||||
SECGROUP string `help:"Secgroup ID or Name" metavar:"Secgroup"`
|
||||
Direction string `help:"Direction of rule" choices:"in|out"`
|
||||
Action string `help:"Action of rule" choices:"allow|deny"`
|
||||
Protocol string `help:"Protocol of rule" choices:"tcp|udp|icmp|any"`
|
||||
Ports string `help:"Ports of rule"`
|
||||
Cidr string `help:"Cidr of rule"`
|
||||
Priority int64 `help:"priority of Rule"`
|
||||
Desc string `help:"Description"`
|
||||
}
|
||||
|
||||
R(&SecGroupRulesCreateOptions{}, "secgroup-rule-create", "Create all security group rule", func(s *mcclient.ClientSession, args *SecGroupRulesCreateOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
if len(args.Desc) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Desc), "description")
|
||||
}
|
||||
if args.Priority > 0 {
|
||||
params.Add(jsonutils.NewInt(args.Priority), "priority")
|
||||
}
|
||||
if len(args.Direction) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Direction), "direction")
|
||||
}
|
||||
if len(args.Action) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Action), "action")
|
||||
}
|
||||
if len(args.Protocol) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Protocol), "protocol")
|
||||
}
|
||||
if len(args.Ports) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Ports), "ports")
|
||||
}
|
||||
if len(args.Cidr) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Cidr), "cidr")
|
||||
}
|
||||
params.Add(jsonutils.NewString(args.SECGROUP), "secgroup")
|
||||
secgrouprules, err := modules.SecGroupRules.Create(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(secgrouprules)
|
||||
return nil
|
||||
})
|
||||
|
||||
type SecGroupRulesUpdateOptions struct {
|
||||
ID string `help:"ID or name of rule"`
|
||||
Name string `help:"New name of rule"`
|
||||
Priority int64 `help:"priority of Rule"`
|
||||
Protocol string `help:"Protocol of rule" choices:"any|tcp|udp|icmp"`
|
||||
Ports string `help:"Ports of rule"`
|
||||
Cidr string `help:"Cidr of rule"`
|
||||
Action string `help:"filter Actin of rule" choices:"allow|deny"`
|
||||
Desc string `help:"Description" metavar:"Description"`
|
||||
}
|
||||
|
||||
R(&SecGroupRulesUpdateOptions{}, "secgroup-rule-update", "Update property of a security group rule", func(s *mcclient.ClientSession, args *SecGroupRulesUpdateOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
if len(args.Name) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Name), "name")
|
||||
}
|
||||
if len(args.Desc) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Desc), "description")
|
||||
}
|
||||
if args.Priority > 0 {
|
||||
params.Add(jsonutils.NewInt(args.Priority), "priority")
|
||||
}
|
||||
if len(args.Protocol) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Protocol), "protocol")
|
||||
}
|
||||
if len(args.Ports) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Ports), "ports")
|
||||
}
|
||||
if len(args.Cidr) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Cidr), "cidr")
|
||||
}
|
||||
if len(args.Action) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Action), "action")
|
||||
}
|
||||
if rule, e := modules.SecGroupRules.Update(s, args.ID, params); e != nil {
|
||||
return e
|
||||
} else {
|
||||
printObject(rule)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
cmd := shell.NewResourceCmd(&modules.SecGroupRules).WithKeyword("secgroup-rule")
|
||||
cmd.List(&compute.SecGroupRulesListOptions{})
|
||||
cmd.Show(&options.BaseShowOptions{})
|
||||
cmd.Delete(&options.BaseIdOptions{})
|
||||
cmd.Create(&compute.SecGroupRulesCreateOptions{})
|
||||
cmd.Update(&compute.SecGroupRulesUpdateOptions{})
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ func init() {
|
||||
type WireListOptions struct {
|
||||
options.BaseListOptions
|
||||
|
||||
Bandwidth *int `help:"List wires by bandwidth"`
|
||||
|
||||
Region string `help:"List wires in region"`
|
||||
Zone string `help:"list wires in zone" json:"-"`
|
||||
Vpc string `help:"List wires in vpc"`
|
||||
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
func init() {
|
||||
type IdentityProviderListOptions struct {
|
||||
options.BaseListOptions
|
||||
SsoDomain string `help:"Filter SSO IDP by domain" json:"sso_domain"`
|
||||
}
|
||||
R(&IdentityProviderListOptions{}, "idp-list", "List all identity provider", func(s *mcclient.ClientSession, args *IdentityProviderListOptions) error {
|
||||
params, err := options.ListStructToParams(args)
|
||||
|
||||
@@ -115,7 +115,9 @@ func init() {
|
||||
Enabled bool `help:"update policy enabled"`
|
||||
Disabled bool `help:"update policy disabled"`
|
||||
Desc string `help:"Description"`
|
||||
IsSystem *bool `help:"is_system"`
|
||||
IsSystem bool `help:"is_system"`
|
||||
|
||||
IsNotSystem bool `help:"negative is_system"`
|
||||
}
|
||||
updateFunc := func(s *mcclient.ClientSession, args *PolicyPatchOptions) error {
|
||||
policyId, err := modules.Policies.GetId(s, args.ID, nil)
|
||||
@@ -141,14 +143,13 @@ func init() {
|
||||
if len(args.Desc) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Desc), "description")
|
||||
}
|
||||
if args.IsSystem != nil {
|
||||
if *args.IsSystem {
|
||||
params.Add(jsonutils.JSONTrue, "is_system")
|
||||
} else {
|
||||
params.Add(jsonutils.JSONFalse, "is_system")
|
||||
}
|
||||
if args.IsSystem {
|
||||
params.Add(jsonutils.JSONTrue, "is_system")
|
||||
}
|
||||
result, err := modules.Policies.Patch(s, policyId, params)
|
||||
if args.IsNotSystem {
|
||||
params.Add(jsonutils.JSONFalse, "is_system")
|
||||
}
|
||||
result, err := modules.Policies.Update(s, policyId, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -167,6 +167,32 @@ func initKubeCluster() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&o.ClusterEnableComponentCephCSIOpt{}, cmdN("component-enable-ceph-csi"), "Enable cluster ceph csi component", func(s *mcclient.ClientSession, args *o.ClusterEnableComponentCephCSIOpt) error {
|
||||
params, err := args.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ret, err := k8s.KubeClusters.PerformAction(s, args.ID, "enable-component", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(ret)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&o.ClusterEnableComponentMonitorOpt{}, cmdN("component-enable-monitor"), "Enable cluster monitor component", func(s *mcclient.ClientSession, args *o.ClusterEnableComponentMonitorOpt) error {
|
||||
params, err := args.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ret, err := k8s.KubeClusters.PerformAction(s, args.ID, "enable-component", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(ret)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&o.ClusterEnableComponentFluentBitOpt{}, cmdN("component-enable-fluentbit"), "Enable cluster fluentbit component", func(s *mcclient.ClientSession, args *o.ClusterEnableComponentFluentBitOpt) error {
|
||||
params, err := args.Params()
|
||||
if err != nil {
|
||||
|
||||
@@ -10,4 +10,5 @@ func init() {
|
||||
cmd := shell.NewResourceCmd(modules.AlertRecordManager)
|
||||
cmd.List(new(options.AlertRecordListOptions))
|
||||
cmd.Show(new(options.AlertRecordShowOptions))
|
||||
cmd.Get("", new(options.AlertRecordTotalOptions))
|
||||
}
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
// 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 monitor
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules/monitor"
|
||||
options "yunion.io/x/onecloud/pkg/mcclient/options/monitor"
|
||||
)
|
||||
|
||||
func init() {
|
||||
aN := cmdN("suggestsysalert")
|
||||
R(&options.SuggestSysAlertListOptions{}, aN("list"), "List all suggestsysrules",
|
||||
func(s *mcclient.ClientSession, args *options.SuggestSysAlertListOptions) error {
|
||||
params, err := args.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(args.Type) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Type), "type")
|
||||
}
|
||||
ret, err := monitor.SuggestSysAlertManager.List(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(ret, monitor.SuggestSysAlertManager.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&options.SSuggestAlertShowOptions{}, aN("show"), "Show details of a alert rule",
|
||||
func(s *mcclient.ClientSession, args *options.SSuggestAlertShowOptions) error {
|
||||
ret, err := monitor.SuggestSysAlertManager.Get(s, args.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(ret)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&options.SuggestAlertIgnoreOptions{}, aN("ignore"), "Ignore alert result",
|
||||
func(s *mcclient.ClientSession, args *options.SuggestAlertIgnoreOptions) error {
|
||||
params, err := args.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ret, err := monitor.SuggestSysAlertManager.PerformAction(s, args.ID, "ignore", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(ret)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -111,7 +111,7 @@ func init() {
|
||||
}
|
||||
R(&ConfigGetTypesOptions{}, "notify-config-get-types", "Get all Config types", func(s *mcclient.ClientSession, args *ConfigGetTypesOptions) error {
|
||||
param := jsonutils.Marshal(args)
|
||||
result, err := modules.NotifyConfig.PerformClassAction(s, "get-types", param)
|
||||
result, err := modules.NotifyReceiver.PerformClassAction(s, "get-types", param)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
12
cmd/climc/shell/suggestion/analysispredict.go
Normal file
12
cmd/climc/shell/suggestion/analysispredict.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package suggestion
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
options "yunion.io/x/onecloud/pkg/mcclient/options/suggestion"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(modules.AnalysisPredictManager)
|
||||
cmd.Get("", new(options.AnalysisPredictConfigOptions))
|
||||
}
|
||||
30
cmd/climc/shell/suggestion/suggestsysalert.go
Normal file
30
cmd/climc/shell/suggestion/suggestsysalert.go
Normal file
@@ -0,0 +1,30 @@
|
||||
// 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 suggestion
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules/monitor"
|
||||
options "yunion.io/x/onecloud/pkg/mcclient/options/monitor"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(monitor.SuggestSysAlertManager)
|
||||
cmd.List(new(options.SuggestSysAlertListOptions))
|
||||
cmd.Show(new(options.SSuggestAlertShowOptions))
|
||||
cmd.Perform("ignore", new(options.SuggestAlertIgnoreOptions))
|
||||
cmd_ := shell.NewResourceCmd(monitor.SuggestSysAlertCostManager)
|
||||
cmd_.Get("", new(options.SuggestAlertCostOptions))
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package monitor
|
||||
package suggestion
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
2
go.mod
2
go.mod
@@ -146,7 +146,7 @@ require (
|
||||
yunion.io/x/ovsdb v0.0.0-20200526071744-27bf0940cbc7
|
||||
yunion.io/x/pkg v0.0.0-20201123083159-ca3aea986ff2
|
||||
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e
|
||||
yunion.io/x/sqlchemy v0.0.0-20201219153152-2d901261898c
|
||||
yunion.io/x/sqlchemy v0.0.0-20210204013753-dbac29c9cedb
|
||||
yunion.io/x/structarg v0.0.0-20200720093445-9f850fa222ce
|
||||
)
|
||||
|
||||
|
||||
4
go.sum
4
go.sum
@@ -931,7 +931,7 @@ yunion.io/x/pkg v0.0.0-20201123083159-ca3aea986ff2 h1:NeCr2J8HjcIuJvEhP0rwWA1UKP
|
||||
yunion.io/x/pkg v0.0.0-20201123083159-ca3aea986ff2/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
|
||||
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e h1:v+EzIadodSwkdZ/7bremd7J8J50Cise/HCylsOJngmo=
|
||||
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e/go.mod h1:0iFKpOs1y4lbCxeOmq3Xx/0AcQoewVPwj62eRluioEo=
|
||||
yunion.io/x/sqlchemy v0.0.0-20201219153152-2d901261898c h1:71nVDQq1oUjvZknEUNfetdiOB1jZMEfmoQlMUaoPIJs=
|
||||
yunion.io/x/sqlchemy v0.0.0-20201219153152-2d901261898c/go.mod h1:FTdwPdGhMgh4E+UFXc9klI1Ok34fMuybTT+jLhOaIjI=
|
||||
yunion.io/x/sqlchemy v0.0.0-20210204013753-dbac29c9cedb h1:k7s5xMCd/fw29vUaNsGCrLkyn7w8eSghJ5NChuU9SAk=
|
||||
yunion.io/x/sqlchemy v0.0.0-20210204013753-dbac29c9cedb/go.mod h1:FTdwPdGhMgh4E+UFXc9klI1Ok34fMuybTT+jLhOaIjI=
|
||||
yunion.io/x/structarg v0.0.0-20200720093445-9f850fa222ce h1:kU8xE7O5uZ1GSJVMZHoJ+jrNL7csUQHYGyAPW9QfNpE=
|
||||
yunion.io/x/structarg v0.0.0-20200720093445-9f850fa222ce/go.mod h1:EP6NSv2C0zzqBDTKumv8hPWLb3XvgMZDHQRfyuOrQng=
|
||||
|
||||
4476
locales/locales.go
4476
locales/locales.go
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -157,6 +157,9 @@ func (h *AuthHandlers) GetRegionsResponse(ctx context.Context, w http.ResponseWr
|
||||
}
|
||||
}
|
||||
resp.Add(domains, "domains")
|
||||
resp.Add(jsonutils.JSONTrue, "return_full_domains")
|
||||
} else {
|
||||
resp.Add(jsonutils.JSONFalse, "return_full_domains")
|
||||
}
|
||||
|
||||
filters := jsonutils.NewDict()
|
||||
@@ -309,9 +312,20 @@ func (h *AuthHandlers) doCredentialLogin(ctx context.Context, req *http.Request,
|
||||
if err != nil {
|
||||
switch httperr := err.(type) {
|
||||
case *httputils.JSONClientError:
|
||||
if httperr.Code >= 500 {
|
||||
return nil, err
|
||||
}
|
||||
if httperr.Code == 409 || httperr.Code == 429 {
|
||||
return nil, err
|
||||
}
|
||||
switch httperr.Class {
|
||||
case "UserNotFound", "WrongPassword":
|
||||
return nil, httperrors.NewJsonClientError(httperrors.ErrIncorrectUsernameOrPassword, "incorrect username or password")
|
||||
case "UserLocked":
|
||||
return nil, httperrors.NewJsonClientError(httperrors.ErrUserLocked, "The user has been locked, please contact the administrator")
|
||||
case "UserDisabled":
|
||||
return nil, httperrors.NewJsonClientError(httperrors.ErrUserDisabled, "The user has been disabled, please contact the administrator")
|
||||
}
|
||||
}
|
||||
return nil, httperrors.NewInvalidCredentialError("invalid credential")
|
||||
}
|
||||
@@ -501,34 +515,34 @@ func (h *AuthHandlers) doLogin(ctx context.Context, w http.ResponseWriter, req *
|
||||
if body.Contains("tenantId") { // switch project
|
||||
token, authToken, err = doTenantLogin(ctx, req, body)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "doTenantLogin")
|
||||
return err
|
||||
}
|
||||
userInfo, err = fetchUserInfoFromToken(ctx, req, token)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetchUserInfoFromToken")
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// user/password authenticate
|
||||
// SSO authentication
|
||||
token, err = h.doCredentialLogin(ctx, req, body)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "doCredentialLogin")
|
||||
return err
|
||||
}
|
||||
userInfo, err = fetchUserInfoFromToken(ctx, req, token)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetchUserInfoFromToken")
|
||||
return err
|
||||
}
|
||||
s := auth.GetAdminSession(ctx, FetchRegion(req), "")
|
||||
isTotpInit, err := isUserTotpCredInitialed(s, token.GetUserId())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "isUserTotpCredInitialed")
|
||||
return err
|
||||
}
|
||||
isIdpLogin := body.Contains("idp_driver")
|
||||
authToken = clientman.NewAuthToken(token.GetTokenString(), isUserEnableTotp(userInfo), isTotpInit, isIdpLogin)
|
||||
}
|
||||
|
||||
if !isUserAllowWebconsole(userInfo) {
|
||||
return errors.Wrap(httperrors.ErrForbidden, "user forbidden login from web")
|
||||
return httperrors.NewForbiddenError("user forbidden login from web")
|
||||
}
|
||||
|
||||
saveAuthCookie(w, authToken, token)
|
||||
@@ -986,6 +1000,12 @@ func getUserInfo2(s *mcclient.ClientSession, uid string, pid string, loginIp str
|
||||
data.Add(jsonutils.JSONFalse, "non_default_domain_projects")
|
||||
}
|
||||
|
||||
if options.Options.EnableQuotaCheck {
|
||||
data.Add(jsonutils.JSONTrue, "enable_quota_check")
|
||||
} else {
|
||||
data.Add(jsonutils.JSONFalse, "enable_quota_check")
|
||||
}
|
||||
|
||||
data.Add(jsonutils.NewString(getSsoCallbackUrl()), "sso_callback_url")
|
||||
|
||||
return data, nil
|
||||
@@ -996,7 +1016,7 @@ func (h *AuthHandlers) getPermissionDetails(ctx context.Context, w http.Response
|
||||
|
||||
_, query, body := appsrv.FetchEnv(ctx, w, req)
|
||||
if body == nil {
|
||||
httperrors.InvalidInputError(ctx, w, "body is empty")
|
||||
httperrors.InvalidInputError(ctx, w, "request body is empty")
|
||||
return
|
||||
}
|
||||
var name string
|
||||
@@ -1030,7 +1050,7 @@ func (h *AuthHandlers) doCreatePolicies(ctx context.Context, w http.ResponseWrit
|
||||
// }
|
||||
_, _, body := appsrv.FetchEnv(ctx, w, req)
|
||||
if body == nil {
|
||||
httperrors.InvalidInputError(ctx, w, "body is empty")
|
||||
httperrors.InvalidInputError(ctx, w, "request body is empty")
|
||||
return
|
||||
}
|
||||
s := auth.GetSession(ctx, t, FetchRegion(req), "")
|
||||
@@ -1114,7 +1134,7 @@ func (h *AuthHandlers) resetUserPassword(ctx context.Context, w http.ResponseWri
|
||||
|
||||
_, _, body := appsrv.FetchEnv(ctx, w, req)
|
||||
if body == nil {
|
||||
httperrors.InvalidInputError(ctx, w, "body is empty")
|
||||
httperrors.InvalidInputError(ctx, w, "request body is empty")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1150,7 +1170,7 @@ func (h *AuthHandlers) resetUserPassword(ctx context.Context, w http.ResponseWri
|
||||
return
|
||||
}
|
||||
}
|
||||
httperrors.InputParameterError(ctx, w, "密码错误")
|
||||
httperrors.InputParameterError(ctx, w, "wrong password")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -205,7 +205,7 @@ func validateTotpRecoverySecrets(s *mcclient.ClientSession, uid string, question
|
||||
func initTotpSecrets(ctx context.Context, w http.ResponseWriter, req *http.Request) {
|
||||
t, authToken, err := fetchAuthInfo(ctx, req)
|
||||
if err != nil {
|
||||
httperrors.InvalidCredentialError(ctx, w, "fetchAuthInfo fail %s", err)
|
||||
httperrors.InvalidCredentialError(ctx, w, "fetchAuthInfo fail: %s", err)
|
||||
return
|
||||
}
|
||||
if authToken.IsTotpInitialized() {
|
||||
@@ -232,14 +232,14 @@ func initTotpSecrets(ctx context.Context, w http.ResponseWriter, req *http.Reque
|
||||
func validatePasscodeHandler(ctx context.Context, w http.ResponseWriter, req *http.Request) {
|
||||
t, authToken, err := fetchAuthInfo(ctx, req)
|
||||
if err != nil {
|
||||
httperrors.InvalidCredentialError(ctx, w, "fetchAuthInfo fail %s", err)
|
||||
httperrors.InvalidCredentialError(ctx, w, "fetchAuthInfo fail: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
s := auth.GetAdminSession(ctx, FetchRegion(req), "")
|
||||
_, _, body := appsrv.FetchEnv(ctx, w, req)
|
||||
if body == nil {
|
||||
httperrors.InvalidInputError(ctx, w, "body is empty")
|
||||
httperrors.InvalidInputError(ctx, w, "request body is empty")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -271,14 +271,14 @@ func validatePasscodeHandler(ctx context.Context, w http.ResponseWriter, req *ht
|
||||
func resetTotpSecrets(ctx context.Context, w http.ResponseWriter, req *http.Request) {
|
||||
t, _, err := fetchAuthInfo(ctx, req)
|
||||
if err != nil {
|
||||
httperrors.InvalidCredentialError(ctx, w, "fetchAuthInfo fail %s", err)
|
||||
httperrors.InvalidCredentialError(ctx, w, "fetchAuthInfo fail: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
s := auth.GetAdminSession(ctx, FetchRegion(req), "")
|
||||
_, _, body := appsrv.FetchEnv(ctx, w, req)
|
||||
if body == nil {
|
||||
httperrors.InvalidInputError(ctx, w, "body is empty")
|
||||
httperrors.InvalidInputError(ctx, w, "request body is empty")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -309,7 +309,7 @@ func resetTotpSecrets(ctx context.Context, w http.ResponseWriter, req *http.Requ
|
||||
func listTotpRecoveryQuestions(ctx context.Context, w http.ResponseWriter, req *http.Request) {
|
||||
t, _, err := fetchAuthInfo(ctx, req)
|
||||
if err != nil {
|
||||
httperrors.InvalidCredentialError(ctx, w, "fetchAuthInfo fail %s", err)
|
||||
httperrors.InvalidCredentialError(ctx, w, "fetchAuthInfo fail: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -335,14 +335,14 @@ func listTotpRecoveryQuestions(ctx context.Context, w http.ResponseWriter, req *
|
||||
func resetTotpRecoveryQuestions(ctx context.Context, w http.ResponseWriter, req *http.Request) {
|
||||
t, _, err := fetchAuthInfo(ctx, req)
|
||||
if err != nil {
|
||||
httperrors.InvalidCredentialError(ctx, w, "fetchAuthInfo fail %s", err)
|
||||
httperrors.InvalidCredentialError(ctx, w, "fetchAuthInfo fail: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
s := auth.GetAdminSession(ctx, FetchRegion(req), "")
|
||||
_, _, body := appsrv.FetchEnv(ctx, w, req)
|
||||
if body == nil {
|
||||
httperrors.InvalidInputError(ctx, w, "body is empty")
|
||||
httperrors.InvalidInputError(ctx, w, "request body is empty")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ func (h *AuthHandlers) handleSsoLogin(ctx context.Context, w http.ResponseWriter
|
||||
case "POST":
|
||||
formData, err := appsrv.Fetch(req)
|
||||
if err != nil {
|
||||
httperrors.InputParameterError(ctx, w, "fetch formdata error: %s", err)
|
||||
httperrors.InputParameterError(ctx, w, "fetch form data error: %s", err)
|
||||
}
|
||||
body, err = jsonutils.ParseQueryString(string(formData))
|
||||
if err != nil {
|
||||
|
||||
@@ -42,6 +42,8 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/util/httputils"
|
||||
)
|
||||
|
||||
const contentTypeSpreadsheet = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||
|
||||
const (
|
||||
HOST_MAC = "*MAC地址"
|
||||
HOST_NAME = "*名称"
|
||||
@@ -154,8 +156,8 @@ func (mh *MiscHandler) DoBatchHostRegister(ctx context.Context, w http.ResponseW
|
||||
|
||||
fileHeader := hostfiles[0].Header
|
||||
contentType := fileHeader.Get("Content-Type")
|
||||
if contentType != "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" {
|
||||
e := httperrors.NewInputParameterError("Wrong content type %s, required application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", contentType)
|
||||
if contentType != contentTypeSpreadsheet {
|
||||
e := httperrors.NewInputParameterError("Wrong content type %s, want %s", contentType, contentTypeSpreadsheet)
|
||||
httperrors.JsonClientError(ctx, w, e)
|
||||
return
|
||||
}
|
||||
@@ -199,7 +201,7 @@ func (mh *MiscHandler) DoBatchHostRegister(ctx context.Context, w http.ResponseW
|
||||
}
|
||||
|
||||
if !titlesOk {
|
||||
httperrors.InputParameterError(ctx, w, "template file is invalid.please check.")
|
||||
httperrors.InputParameterError(ctx, w, "template file is invalid. please check.")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -302,8 +304,8 @@ func (mh *MiscHandler) DoBatchUserRegister(ctx context.Context, w http.ResponseW
|
||||
|
||||
fileHeader := userfiles[0].Header
|
||||
contentType := fileHeader.Get("Content-Type")
|
||||
if contentType != "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" {
|
||||
e := httperrors.NewInputParameterError("Wrong content type %s, required application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", contentType)
|
||||
if contentType != contentTypeSpreadsheet {
|
||||
e := httperrors.NewInputParameterError("Wrong content type %s, want %s", contentType, contentTypeSpreadsheet)
|
||||
httperrors.JsonClientError(ctx, w, e)
|
||||
return
|
||||
}
|
||||
@@ -328,7 +330,7 @@ func (mh *MiscHandler) DoBatchUserRegister(ctx context.Context, w http.ResponseW
|
||||
// skipped header row
|
||||
rows := xlsx.GetRows("users")
|
||||
if len(rows) <= 1 {
|
||||
e := httperrors.NewInputParameterError("empty file")
|
||||
e := httperrors.NewInputParameterError("empty file content")
|
||||
httperrors.JsonClientError(ctx, w, e)
|
||||
return
|
||||
} else if len(rows) > BATCH_USER_REGISTER_QUANTITY_LIMITATION {
|
||||
@@ -431,7 +433,7 @@ func (mh *MiscHandler) getDownloadsHandler(ctx context.Context, w http.ResponseW
|
||||
params := appctx.AppContextParams(ctx)
|
||||
template, ok := params["<template_id>"]
|
||||
if !ok || len(template) == 0 {
|
||||
httperrors.InvalidInputError(ctx, w, "not found")
|
||||
httperrors.InvalidInputError(ctx, w, "template_id")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -142,11 +142,11 @@ func fetchIdList(ctx context.Context, query jsonutils.JSONObject, w http.Respons
|
||||
if e == nil && len(idlist) > 0 {
|
||||
queryDict := query.(*jsonutils.JSONDict)
|
||||
queryDict.Remove("id")
|
||||
log.Debugf("Get idlist: %s", idlist)
|
||||
log.Debugf("Get id list: %s", idlist)
|
||||
return jsonutils.JSONArray2StringArray(idlist)
|
||||
} else {
|
||||
log.Debugf("Cannot find idlist in query: %s", query)
|
||||
httperrors.InvalidInputError(ctx, w, "No idlist found")
|
||||
log.Debugf("Cannot find id list in query: %s", query)
|
||||
httperrors.InvalidInputError(ctx, w, "No id list found")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
|
||||
type CloudeventListInput struct {
|
||||
apis.ModelBaseListInput
|
||||
apis.ProjectizedResourceListInput
|
||||
apis.DomainizedResourceListInput
|
||||
|
||||
compute.CloudenvResourceListInput
|
||||
|
||||
@@ -47,6 +47,6 @@ type CloudeventListInput struct {
|
||||
|
||||
type CloudeventDetails struct {
|
||||
apis.ModelBaseDetails
|
||||
apis.ProjectizedResourceInfo
|
||||
apis.DomainizedResourceInfo
|
||||
SCloudevent
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ type CloudroleListInput struct {
|
||||
apis.StatusInfrasResourceBaseListInput
|
||||
|
||||
CloudaccountResourceListInput
|
||||
CloudgroupResourceListInput
|
||||
}
|
||||
|
||||
type CloudroleDetails struct {
|
||||
|
||||
@@ -114,6 +114,7 @@ const (
|
||||
CITY_SOUTH_CAROLINA = "South Carolina" //南卡罗来纳州
|
||||
CITY_SALT_LAKE_CITY = "Salt Lake City" //盐湖城
|
||||
CITY_LAS_VEGAS = "Las Vegas" //拉斯维加斯
|
||||
CITY_PHOENIX = "Phoenix" //菲尼克斯
|
||||
|
||||
// 英国
|
||||
CITY_LONDON = "London" //伦敦
|
||||
@@ -150,7 +151,8 @@ const (
|
||||
CITY_STOCKHOLM = "Stockholm" //斯德哥尔摩
|
||||
|
||||
// 巴西
|
||||
CITY_SAO_PAULO = "Sao Paulo" //圣保罗
|
||||
CITY_SAO_PAULO = "Sao Paulo" //圣保罗
|
||||
CITY_RIO_DE_JANEIRO = "Rio de Janeiro" // 里约热内卢
|
||||
|
||||
// 智利
|
||||
CITY_SANTIAGO = "Santiago" // 圣地亚哥
|
||||
|
||||
@@ -294,6 +294,8 @@ type DBInstanceDetails struct {
|
||||
|
||||
SDBInstance
|
||||
|
||||
Secgroups []apis.StandaloneShortDesc `json:"secgroups"`
|
||||
|
||||
// 安全组名称
|
||||
// example: Default
|
||||
Secgroup string `json:"secgroup"`
|
||||
|
||||
@@ -372,7 +372,10 @@ type GuestMigrateInput struct {
|
||||
}
|
||||
|
||||
type GuestLiveMigrateInput struct {
|
||||
// 指定期望的迁移目标宿主机
|
||||
PreferHost string `json:"prefer_host"`
|
||||
// 是否跳过CPU检查,默认要做CPU检查
|
||||
SkipCpuCheck *bool `json:"skip_cpu_check"`
|
||||
}
|
||||
|
||||
type GuestSetSecgroupInput struct {
|
||||
|
||||
@@ -72,6 +72,8 @@ type HostListInput struct {
|
||||
ResourceType string `json:"resource_type"`
|
||||
// filter by mac of any network interface
|
||||
AnyMac string `json:"any_mac"`
|
||||
// filter by ip of any network interface
|
||||
AnyIp string `json:"any_ip"`
|
||||
// filter storages not attached to this host
|
||||
StorageNotAttached *bool `json:"storage_not_attached"`
|
||||
// filter by Hypervisor
|
||||
|
||||
@@ -23,6 +23,9 @@ import (
|
||||
type ScheduledTaskDetails struct {
|
||||
apis.VirtualResourceDetails
|
||||
SScheduledTask
|
||||
|
||||
// 描述
|
||||
TimerDesc string `json:"timer_desc"`
|
||||
// 定时方式触发
|
||||
Timer TimerDetails `json:"timer"`
|
||||
// 周期方式触发
|
||||
|
||||
@@ -24,14 +24,12 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
)
|
||||
|
||||
type SSecgroupRuleCreateInput struct {
|
||||
apis.ResourceBaseCreateInput
|
||||
|
||||
type SSecgroupRuleResource struct {
|
||||
// 优先级, 数字越大优先级越高
|
||||
// minimum: 1
|
||||
// maximum: 100
|
||||
// required: true
|
||||
Priority int `json:"priority"`
|
||||
Priority *int `json:"priority"`
|
||||
|
||||
// 协议
|
||||
// required: true
|
||||
@@ -68,7 +66,7 @@ type SSecgroupRuleCreateInput struct {
|
||||
// required: true
|
||||
Direction string `json:"direction"`
|
||||
|
||||
// ip或cidr地址
|
||||
// ip或cidr地址, 若指定peer_secgroup_id此参数不生效
|
||||
// example: 192.168.222.121
|
||||
CIDR string `json:"cidr"`
|
||||
|
||||
@@ -84,17 +82,36 @@ type SSecgroupRuleCreateInput struct {
|
||||
// example: test to create rule
|
||||
Description string `json:"description"`
|
||||
|
||||
// 仅单独创建安全组规则时需要指定安全组
|
||||
// required: true
|
||||
Secgroup string `json:"secgroup"`
|
||||
|
||||
// swagger:ignore
|
||||
SecgroupId string
|
||||
// 对端安全组Id, 此参数和cidr参数互斥,并且优先级高于cidr, 同事peer_secgroup_id不能和它所在的安全组ID相同
|
||||
// required: false
|
||||
PeerSecgroupId string `json:"peer_secgroup_id"`
|
||||
}
|
||||
|
||||
func (input *SSecgroupRuleCreateInput) Check() error {
|
||||
type SSecgroupRuleCreateInput struct {
|
||||
apis.ResourceBaseCreateInput
|
||||
SSecgroupRuleResource
|
||||
|
||||
// swagger:ignore
|
||||
Secgroup string `json:"secgroup" yunion-deprecated-by:"secgroup_id"`
|
||||
|
||||
// 安全组ID
|
||||
// required: true
|
||||
SecgroupId string `json:"secgroup_id"`
|
||||
}
|
||||
|
||||
type SSecgroupRuleUpdateInput struct {
|
||||
apis.ResourceBaseUpdateInput
|
||||
|
||||
SSecgroupRuleResource
|
||||
}
|
||||
|
||||
func (input *SSecgroupRuleResource) Check() error {
|
||||
priority := 1
|
||||
if input.Priority != nil {
|
||||
priority = *input.Priority
|
||||
}
|
||||
rule := secrules.SecurityRule{
|
||||
Priority: input.Priority,
|
||||
Priority: priority,
|
||||
Direction: secrules.TSecurityRuleDirection(input.Direction),
|
||||
Action: secrules.TSecurityRuleAction(input.Action),
|
||||
Protocol: input.Protocol,
|
||||
|
||||
@@ -22,5 +22,6 @@ type SecgroupRuleDetails struct {
|
||||
SSecurityGroupRule
|
||||
SecurityGroupResourceInfo
|
||||
|
||||
ProjectId string `json:"tenant_id"`
|
||||
ProjectId string `json:"tenant_id"`
|
||||
PeerSecgroup string `json:"peer_secgroup"`
|
||||
}
|
||||
|
||||
@@ -19,12 +19,13 @@ const (
|
||||
SNAPSHOT_MANUAL = "manual"
|
||||
SNAPSHOT_AUTO = "auto"
|
||||
|
||||
SNAPSHOT_CREATING = "creating"
|
||||
SNAPSHOT_ROLLBACKING = "rollbacking"
|
||||
SNAPSHOT_FAILED = "create_failed"
|
||||
SNAPSHOT_READY = "ready"
|
||||
SNAPSHOT_DELETING = "deleting"
|
||||
SNAPSHOT_UNKNOWN = "unknown"
|
||||
SNAPSHOT_CREATING = "creating"
|
||||
SNAPSHOT_ROLLBACKING = "rollbacking"
|
||||
SNAPSHOT_FAILED = "create_failed"
|
||||
SNAPSHOT_READY = "ready"
|
||||
SNAPSHOT_DELETE_FAILED = "delete_failed"
|
||||
SNAPSHOT_DELETING = "deleting"
|
||||
SNAPSHOT_UNKNOWN = "unknown"
|
||||
|
||||
SNAPSHOT_POLICY_CREATING = "creating"
|
||||
|
||||
|
||||
@@ -146,6 +146,25 @@ var (
|
||||
SHARED_STORAGE = []string{STORAGE_NFS, STORAGE_GPFS, STORAGE_RBD}
|
||||
)
|
||||
|
||||
func IsDiskTypeMatch(t1, t2 string) bool {
|
||||
switch t1 {
|
||||
case DISK_TYPE_ROTATE:
|
||||
if t2 == DISK_TYPE_SSD {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
case DISK_TYPE_SSD:
|
||||
if t2 == DISK_TYPE_ROTATE {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
type StorageResourceInput struct {
|
||||
// 存储(ID或Name)
|
||||
StorageId string `json:"storage_id"`
|
||||
|
||||
@@ -33,6 +33,8 @@ const (
|
||||
|
||||
DEFAULT_VPC_ID = "default"
|
||||
NORMAL_VPC_ID = "normal" // 没有关联VPC的安全组,统一使用normal
|
||||
|
||||
CLASSIC_VPC_NAME = "-"
|
||||
)
|
||||
|
||||
type UsableResourceListInput struct {
|
||||
|
||||
@@ -87,4 +87,6 @@ type WireListInput struct {
|
||||
ZonalFilterListBase
|
||||
|
||||
HostResourceInput
|
||||
|
||||
Bandwidth *int `json:"bandwidth"`
|
||||
}
|
||||
|
||||
@@ -2068,7 +2068,6 @@ type SScheduledTask struct {
|
||||
apis.SEnabledResourceBase
|
||||
ScheduledType string `json:"scheduled_type"`
|
||||
STimer
|
||||
TimerDesc string `json:"timer_desc"`
|
||||
ResourceType string `json:"resource_type"`
|
||||
Operation string `json:"operation"`
|
||||
LabelType string `json:"label_type"`
|
||||
|
||||
@@ -31,11 +31,12 @@ type SUserExtended struct {
|
||||
Email string
|
||||
Mobile string
|
||||
|
||||
LocalId int
|
||||
LocalName string
|
||||
DomainName string
|
||||
DomainEnabled bool
|
||||
IsLocal bool
|
||||
LocalId int
|
||||
LocalName string
|
||||
LocalFailedAuthCount int
|
||||
DomainName string
|
||||
DomainEnabled bool
|
||||
IsLocal bool
|
||||
// IdpId string
|
||||
// IdpName string
|
||||
}
|
||||
|
||||
@@ -205,6 +205,8 @@ type PerformStatusInput struct {
|
||||
// 更改的目标状态值
|
||||
// required:true
|
||||
Status string `json:"status"`
|
||||
// swagger:ignore
|
||||
BlockJobsCount int `json:"block_jobs_count"`
|
||||
|
||||
// 更改状态的原因描述
|
||||
// required:false
|
||||
|
||||
@@ -22,7 +22,7 @@ type AlertResourceType string
|
||||
|
||||
const (
|
||||
// AlertResourceTypeNode means onecloud system infrastructure controller or host node
|
||||
AlertResourceTypeNode AlertResourceType = "node"
|
||||
AlertResourceTypeNode AlertResourceType = "host"
|
||||
// AlertResourceTypeCloudaccount means cloudaccount resource
|
||||
AlertResourceTypeCloudaccount AlertResourceType = "cloudaccount"
|
||||
// AlertResourceTypeVM means virtual machine guest resource
|
||||
|
||||
@@ -120,10 +120,11 @@ type CommonAlertDetails struct {
|
||||
}
|
||||
|
||||
type CommonAlertMetricDetails struct {
|
||||
Comparator string `json:"comparator"`
|
||||
Threshold float64 `json:"threshold"`
|
||||
ConditionType string `json:"condition_type"`
|
||||
ThresholdStr string `json:"threshold_str"`
|
||||
Comparator string `json:"comparator"`
|
||||
Threshold float64 `json:"threshold"`
|
||||
WithinRange []float64 `json:"within_range"`
|
||||
ConditionType string `json:"condition_type"`
|
||||
ThresholdStr string `json:"threshold_str"`
|
||||
// metric points'value的运算方式
|
||||
Reduce string `json:"reduce"`
|
||||
DB string `json:"db"`
|
||||
|
||||
@@ -30,8 +30,8 @@ var (
|
||||
MetricUnit = []string{METRIC_UNIT_PERCENT, METRIC_UNIT_BPS, METRIC_UNIT_MBPS, METRIC_UNIT_BYTEPS, "count/s",
|
||||
METRIC_UNIT_COUNT, METRIC_UNIT_MS, METRIC_UNIT_BYTE, METRIC_UNIT_RMB}
|
||||
ResTypeScoreMap = map[string]int{
|
||||
METRIC_RES_TYPE_HOST: 1,
|
||||
METRIC_RES_TYPE_GUEST: 2,
|
||||
METRIC_RES_TYPE_GUEST: 1,
|
||||
METRIC_RES_TYPE_HOST: 2,
|
||||
METRIC_RES_TYPE_OSS: 3,
|
||||
METRIC_RES_TYPE_RDS: 4,
|
||||
METRIC_RES_TYPE_REDIS: 5,
|
||||
|
||||
@@ -62,6 +62,9 @@ const (
|
||||
TEMPLATE_TYPE_CONTENT = "content"
|
||||
TEMPLATE_TYPE_REMOTE = "remote"
|
||||
|
||||
TEMPLATE_LANG_EN = "en"
|
||||
TEMPLATE_LANG_CN = "cn"
|
||||
|
||||
CTYPE_ROBOT_YES = "yes"
|
||||
CTYPE_ROBOT_ONLY = "only"
|
||||
)
|
||||
|
||||
@@ -82,6 +82,8 @@ type ScheduleInput struct {
|
||||
CpuMode string `json:"cpu_mode"`
|
||||
OsArch string `json:"os_arch"`
|
||||
|
||||
SkipCpuCheck *bool `json:"skip_cpu_check"`
|
||||
|
||||
// In the migrate and create backup cases
|
||||
// we don't need reallocate network
|
||||
ReuseNetwork bool `json:"reuse_network"`
|
||||
|
||||
@@ -27,7 +27,7 @@ type IPMIProfile struct {
|
||||
|
||||
func DefaultProfile() IPMIProfile {
|
||||
return IPMIProfile{
|
||||
LanChannel: []int{1},
|
||||
LanChannel: []int{1, 2, 8},
|
||||
RootName: "root",
|
||||
RootId: 2,
|
||||
}
|
||||
@@ -84,14 +84,24 @@ func QemuProfile() IPMIProfile {
|
||||
}
|
||||
}
|
||||
|
||||
func H3CProfile() IPMIProfile {
|
||||
return IPMIProfile{
|
||||
LanChannel: []int{8, 1},
|
||||
RootName: "root",
|
||||
RootId: 2,
|
||||
StrongPass: true,
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
PROFILES map[string]IPMIProfile = map[string]IPMIProfile{
|
||||
"inspur": InspurProfile(),
|
||||
"lenovo": LenovoProfile(),
|
||||
"hp": HpProfile(),
|
||||
"huawei": HuaweiProfile(),
|
||||
"foxconn": FoxconnProfile(),
|
||||
"qemu": QemuProfile(),
|
||||
types.OEM_NAME_INSPUR: InspurProfile(),
|
||||
types.OEM_NAME_LENOVO: LenovoProfile(),
|
||||
types.OEM_NAME_HP: HpProfile(),
|
||||
types.OEM_NAME_HUAWEI: HuaweiProfile(),
|
||||
types.OEM_NAME_FOXCONN: FoxconnProfile(),
|
||||
types.OEM_NAME_QEMU: QemuProfile(),
|
||||
types.OEM_NAME_H3C: H3CProfile(),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -459,17 +459,17 @@ func (manager *SMetadataManager) SetValue(ctx context.Context, obj IModel, key s
|
||||
}
|
||||
|
||||
func (manager *SMetadataManager) SetValuesWithLog(ctx context.Context, obj IModel, store map[string]interface{}, userCred mcclient.TokenCredential) error {
|
||||
changes, err := manager.SetValues(ctx, obj, store, userCred)
|
||||
changes, err := manager.setValues(ctx, obj, store, userCred)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(changes) > 0 {
|
||||
OpsLog.LogEvent(obj, ACT_SET_METADATA, jsonutils.Marshal(changes), userCred)
|
||||
OpsLog.LogEvent(obj.GetIModel(), ACT_SET_METADATA, jsonutils.Marshal(changes), userCred)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SMetadataManager) SetValues(ctx context.Context, obj IModel, store map[string]interface{}, userCred mcclient.TokenCredential) ([]sMetadataChange, error) {
|
||||
func (manager *SMetadataManager) setValues(ctx context.Context, obj IModel, store map[string]interface{}, userCred mcclient.TokenCredential) ([]sMetadataChange, error) {
|
||||
idStr := GetObjectIdstr(obj)
|
||||
|
||||
// no need to lock
|
||||
@@ -546,9 +546,9 @@ func (manager *SMetadataManager) SetValues(ctx context.Context, obj IModel, stor
|
||||
}
|
||||
|
||||
func (manager *SMetadataManager) SetAll(ctx context.Context, obj IModel, store map[string]interface{}, userCred mcclient.TokenCredential, delRange string) error {
|
||||
changes, err := manager.SetValues(ctx, obj, store, userCred)
|
||||
changes, err := manager.setValues(ctx, obj, store, userCred)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "setValues")
|
||||
}
|
||||
|
||||
idStr := GetObjectIdstr(obj)
|
||||
@@ -565,9 +565,9 @@ func (manager *SMetadataManager) SetAll(ctx context.Context, obj IModel, store m
|
||||
q := manager.Query().Equals("id", idStr).NotLike("key", `\_\_%`) //避免删除系统内置的metadata, _ 在mysql里面有特殊含义,需要转义
|
||||
switch delRange {
|
||||
case USER_TAG_PREFIX:
|
||||
q = q.Like("key", USER_TAG_PREFIX+"%")
|
||||
q = q.Startswith("key", USER_TAG_PREFIX)
|
||||
case CLOUD_TAG_PREFIX:
|
||||
q = q.Like("key", CLOUD_TAG_PREFIX+"%")
|
||||
q = q.Startswith("key", CLOUD_TAG_PREFIX)
|
||||
}
|
||||
q = q.Filter(sqlchemy.NOT(sqlchemy.In(q.Field("key"), keys)))
|
||||
if err := FetchModelObjects(manager, q, &records); err != nil {
|
||||
@@ -581,7 +581,7 @@ func (manager *SMetadataManager) SetAll(ctx context.Context, obj IModel, store m
|
||||
changes = append(changes, sMetadataChange{Key: rec.Key, OValue: rec.Value})
|
||||
}
|
||||
if len(changes) > 0 {
|
||||
OpsLog.LogEvent(obj, ACT_SET_METADATA, jsonutils.Marshal(changes), userCred)
|
||||
OpsLog.LogEvent(obj.GetIModel(), ACT_SET_METADATA, jsonutils.Marshal(changes), userCred)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -603,7 +603,7 @@ func (manager *SMetadataManager) GetAll(obj IModel, keys []string, keyPrefix str
|
||||
ret := make(map[string]string)
|
||||
for _, rec := range records {
|
||||
if len(rec.Value) > 0 || strings.HasPrefix(rec.Key, USER_TAG_PREFIX) {
|
||||
ret[rec.Key] = rec.Value
|
||||
ret[strings.ToLower(rec.Key)] = rec.Value
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
|
||||
@@ -126,7 +126,8 @@ func (manager *SOpsLogManager) LogEvent(model IModel, action string, notes inter
|
||||
if !consts.OpsLogEnabled() {
|
||||
return
|
||||
}
|
||||
if len(model.GetId()) == 0 || len(model.GetName()) == 0 {
|
||||
if len(model.GetId()) == 0 {
|
||||
log.Errorf("logevent for an object without ID???")
|
||||
return
|
||||
}
|
||||
if action == ACT_UPDATE {
|
||||
|
||||
@@ -47,8 +47,9 @@ const (
|
||||
ACT_BACKUP_START = "backup_start"
|
||||
ACT_BACKUP_START_FAILED = "backup_start_fail"
|
||||
|
||||
ACT_FREEZE = "freeze"
|
||||
ACT_UNFREEZE = "unfreeze"
|
||||
ACT_FREEZE = "freeze"
|
||||
ACT_FREEZE_FAIL = "freeze_fail"
|
||||
ACT_UNFREEZE = "unfreeze"
|
||||
|
||||
ACT_RESTARING = "restarting"
|
||||
ACT_RESTART_FAIL = "restart_fail"
|
||||
|
||||
@@ -51,6 +51,8 @@ func isObjectRbacAllowed(model IModel, userCred mcclient.TokenCredential, action
|
||||
case rbacutils.ScopeUser:
|
||||
if ownerId != nil && objOwnerId != nil && (ownerId.GetUserId() == objOwnerId.GetUserId() || objOwnerId.GetUserId() == "" || (model.IsSharable(ownerId) && action == policy.PolicyActionGet)) {
|
||||
requireScope = rbacutils.ScopeUser
|
||||
} else if ownerId != nil && objOwnerId != nil && ownerId.GetProjectDomainId() == objOwnerId.GetProjectDomainId() {
|
||||
requireScope = rbacutils.ScopeDomain
|
||||
} else {
|
||||
requireScope = rbacutils.ScopeSystem
|
||||
}
|
||||
@@ -103,6 +105,8 @@ func isClassRbacAllowed(manager IModelManager, userCred mcclient.TokenCredential
|
||||
case rbacutils.ScopeUser:
|
||||
if ownerId != nil && ownerId.GetUserId() == objOwnerId.GetUserId() {
|
||||
requireScope = rbacutils.ScopeUser
|
||||
} else if ownerId != nil && ownerId.GetProjectDomainId() == objOwnerId.GetProjectDomainId() {
|
||||
requireScope = rbacutils.ScopeDomain
|
||||
} else {
|
||||
requireScope = rbacutils.ScopeSystem
|
||||
}
|
||||
|
||||
@@ -433,14 +433,9 @@ func notifyWithChannel(ctx context.Context, p sNotifyParams, channels ...npk.TNo
|
||||
p.recipientId = []string{}
|
||||
p.contacts = []string{}
|
||||
p.channel = c
|
||||
if c == npk.NotifyByWebConsole {
|
||||
p.contacts = reps
|
||||
} else {
|
||||
p.recipientId = reps
|
||||
}
|
||||
p.recipientId = reps
|
||||
rawNotify(ctx, p)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func NotifyImportant(recipientId []string, isGroup bool, event string, data jsonutils.JSONObject) {
|
||||
@@ -519,7 +514,7 @@ func notifyRobot(ctx context.Context, robot string, recipientId []string, isGrou
|
||||
s := auth.GetAdminSession(ctx, consts.GetRegion(), "")
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("robot", jsonutils.NewString(robot))
|
||||
result, err := modules.NotifyConfig.PerformClassAction(s, "get-types", params)
|
||||
result, err := modules.NotifyReceiver.PerformClassAction(s, "get-types", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ const (
|
||||
OEM_NAME_FOXCONN = "foxconn"
|
||||
OEM_NAME_QEMU = "qemu"
|
||||
OEM_NAME_SUPERMICRO = "supermicro"
|
||||
OEM_NAME_H3C = "h3c"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -48,6 +49,7 @@ var (
|
||||
OEM_NAME_FOXCONN,
|
||||
OEM_NAME_QEMU,
|
||||
OEM_NAME_SUPERMICRO,
|
||||
OEM_NAME_H3C,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -829,6 +829,9 @@ var ValidateModel = func(userCred mcclient.TokenCredential, manager db.IStandalo
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError2(manager.Keyword(), *id)
|
||||
}
|
||||
if errors.Cause(err) == sqlchemy.ErrDuplicateEntry {
|
||||
return nil, httperrors.NewDuplicateResourceError(manager.Keyword(), *id)
|
||||
}
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
*id = model.GetId()
|
||||
|
||||
@@ -34,7 +34,7 @@ import (
|
||||
|
||||
type SCloudeventManager struct {
|
||||
db.SModelBaseManager
|
||||
db.SProjectizedResourceBaseManager
|
||||
db.SDomainizedResourceBaseManager
|
||||
}
|
||||
|
||||
var CloudeventManager *SCloudeventManager
|
||||
@@ -57,7 +57,7 @@ func init() {
|
||||
|
||||
type SCloudevent struct {
|
||||
db.SModelBase
|
||||
db.SProjectizedResourceBase
|
||||
db.SDomainizedResourceBase
|
||||
|
||||
EventId int64 `primary:"true" auto_increment:"true" list:"user"`
|
||||
Name string `width:"128" charset:"utf8" nullable:"false" index:"true" list:"user"`
|
||||
@@ -76,6 +76,10 @@ type SCloudevent struct {
|
||||
Brand string `width:"64" charset:"ascii" list:"domain"`
|
||||
}
|
||||
|
||||
func (self *SCloudeventManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return db.IsDomainAllowList(userCred, self)
|
||||
}
|
||||
|
||||
func (self *SCloudeventManager) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return false
|
||||
}
|
||||
@@ -88,6 +92,10 @@ func (self *SCloudevent) AllowUpdateItem(ctx context.Context, userCred mcclient.
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SCloudevent) AllowGetDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return db.IsDomainAllowGet(userCred, self)
|
||||
}
|
||||
|
||||
// 云平台操作日志列表
|
||||
func (manager *SCloudeventManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
@@ -97,7 +105,11 @@ func (manager *SCloudeventManager) ListItemFilter(
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
q, err := manager.SModelBaseManager.ListItemFilter(ctx, q, userCred, input.ModelBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SVirtualResourceBaseManager.ListItemFilter")
|
||||
return nil, errors.Wrap(err, "SModelBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SDomainizedResourceBaseManager.ListItemFilter(ctx, q, userCred, input.DomainizedResourceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SDomainizedResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
|
||||
if len(input.Providers) > 0 {
|
||||
@@ -153,37 +165,45 @@ func (manager *SCloudeventManager) FetchCustomizeColumns(
|
||||
) []api.CloudeventDetails {
|
||||
rows := make([]api.CloudeventDetails, len(objs))
|
||||
base := manager.SModelBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
projRows := manager.SProjectizedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
domainRows := manager.SDomainizedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
for i := range rows {
|
||||
rows[i].ModelBaseDetails = base[i]
|
||||
rows[i].ProjectizedResourceInfo = projRows[i]
|
||||
rows[i].DomainizedResourceInfo = domainRows[i]
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
func (self *SCloudevent) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
return self.SModelBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
|
||||
}
|
||||
|
||||
func (manager *SCloudeventManager) NamespaceScope() rbacutils.TRbacScope {
|
||||
return rbacutils.ScopeDomain
|
||||
}
|
||||
|
||||
func (manager *SCloudeventManager) ResourceScope() rbacutils.TRbacScope {
|
||||
return rbacutils.ScopeProject
|
||||
return rbacutils.ScopeDomain
|
||||
}
|
||||
|
||||
func (self *SCloudevent) GetOwnerId() mcclient.IIdentityProvider {
|
||||
owner := db.SOwnerId{DomainId: self.DomainId, ProjectId: self.ProjectId}
|
||||
owner := db.SOwnerId{DomainId: self.DomainId}
|
||||
return &owner
|
||||
}
|
||||
|
||||
func (manager *SCloudeventManager) FilterByOwner(q *sqlchemy.SQuery, owner mcclient.IIdentityProvider, scope rbacutils.TRbacScope) *sqlchemy.SQuery {
|
||||
return manager.SProjectizedResourceBaseManager.FilterByOwner(q, owner, scope)
|
||||
return manager.SDomainizedResourceBaseManager.FilterByOwner(q, owner, scope)
|
||||
}
|
||||
|
||||
func (manager *SCloudeventManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) {
|
||||
return manager.SProjectizedResourceBaseManager.FetchOwnerId(ctx, data)
|
||||
return manager.SDomainizedResourceBaseManager.FetchOwnerId(ctx, data)
|
||||
}
|
||||
|
||||
func (manager *SCloudeventManager) ListItemExportKeys(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, keys stringutils2.SSortedStrings) (*sqlchemy.SQuery, error) {
|
||||
return manager.SProjectizedResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
return manager.SDomainizedResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
}
|
||||
|
||||
func (manager *SCloudeventManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
|
||||
return manager.SProjectizedResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
return manager.SDomainizedResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
}
|
||||
|
||||
func (manager *SCloudeventManager) OrderByExtraFields(
|
||||
@@ -192,7 +212,7 @@ func (manager *SCloudeventManager) OrderByExtraFields(
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.CloudeventListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
return manager.SProjectizedResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.ProjectizedResourceListInput)
|
||||
return manager.SDomainizedResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.DomainizedResourceListInput)
|
||||
}
|
||||
|
||||
func (manager *SCloudeventManager) SyncCloudevent(ctx context.Context, userCred mcclient.TokenCredential, cloudprovider *SCloudprovider, iEvents []cloudprovider.ICloudEvent) int {
|
||||
@@ -213,7 +233,6 @@ func (manager *SCloudeventManager) SyncCloudevent(ctx context.Context, userCred
|
||||
CloudproviderId: cloudprovider.Id,
|
||||
}
|
||||
event.DomainId = cloudprovider.DomainId
|
||||
event.ProjectId = cloudprovider.ProjectId
|
||||
if len(event.Brand) == 0 {
|
||||
event.Brand = event.Provider
|
||||
}
|
||||
|
||||
@@ -279,23 +279,12 @@ func (self *SCloudprovider) GetNextTimeRange() (time.Time, time.Time, error) {
|
||||
if err != nil {
|
||||
return start, end, errors.Wrap(err, "self.GetProviderFactory")
|
||||
}
|
||||
q := CloudeventManager.Query().Equals("cloudprovider_id", self.Id).Desc("created_at")
|
||||
count, err := q.CountWithError()
|
||||
if err != nil {
|
||||
return start, end, errors.Wrap(err, "q.CountWithError")
|
||||
}
|
||||
if !self.LastSyncTimeAt.IsZero() {
|
||||
start = self.LastSyncTimeAt
|
||||
} else if count == 0 {
|
||||
start = time.Now().AddDate(0, 0, -1*factory.GetMaxCloudEventKeepDays())
|
||||
} else {
|
||||
event := &SCloudevent{}
|
||||
err = q.First(event)
|
||||
if err != nil {
|
||||
return start, end, errors.Wrap(err, "q.First")
|
||||
}
|
||||
start = event.CreatedAt
|
||||
start = time.Now().AddDate(0, 0, -1*factory.GetMaxCloudEventKeepDays())
|
||||
}
|
||||
|
||||
// 避免cloudevent过长时间未运行,再次运行时记录的最后一条时间距离现在间隔太长
|
||||
if start.Before(time.Now().AddDate(0, 0, factory.GetMaxCloudEventKeepDays()*-1)) {
|
||||
start = time.Now().AddDate(0, 0, factory.GetMaxCloudEventKeepDays()*-1)
|
||||
|
||||
@@ -21,8 +21,10 @@ import (
|
||||
|
||||
var (
|
||||
cloudeventSystemResources = []string{}
|
||||
cloudeventDomainResources = []string{}
|
||||
cloudeventUserResources = []string{}
|
||||
cloudeventDomainResources = []string{
|
||||
"cloudevents",
|
||||
}
|
||||
cloudeventUserResources = []string{}
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -383,6 +383,10 @@ func (manager *SCloudaccountManager) SyncCloudaccounts(ctx context.Context, user
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) StartSyncSamlProvidersTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
if self.SAMLAuth.IsFalse() {
|
||||
log.Debugf("cloudaccount %s(%s) not enable saml auth, skip sycing saml provider", self.Name, self.Provider)
|
||||
return nil
|
||||
}
|
||||
params := jsonutils.NewDict()
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "SyncSAMLProvidersTask", self, userCred, params, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
@@ -1635,9 +1639,14 @@ func (self *SCloudaccount) SyncSystemCloudpoliciesForCloud(ctx context.Context,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) GetLocalUserCloudroles(userId, spId string) ([]SCloudrole, error) {
|
||||
func (self *SCloudaccount) GetLocalCloudroles(userId, groupId string, spId string, grouped bool) ([]SCloudrole, error) {
|
||||
roles := []SCloudrole{}
|
||||
q := CloudroleManager.Query().Equals("cloudaccount_id", self.Id).Equals("owner_id", userId).Equals("saml_provider_id", spId)
|
||||
q := CloudroleManager.Query().Equals("cloudaccount_id", self.Id).Equals("saml_provider_id", spId)
|
||||
if grouped {
|
||||
q = q.Equals("cloudgroup_id", groupId)
|
||||
} else {
|
||||
q = q.Equals("owner_id", userId)
|
||||
}
|
||||
err := db.FetchModelObjects(CloudroleManager, q, &roles)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
@@ -1645,55 +1654,90 @@ func (self *SCloudaccount) GetLocalUserCloudroles(userId, spId string) ([]SCloud
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) RegisterCloudrole(userId, spId string) (*SCloudrole, error) {
|
||||
roles, err := self.GetLocalUserCloudroles(userId, spId)
|
||||
func (self *SCloudaccount) RegisterCloudroles(userId string, grouped bool, spId string) ([]SCloudrole, error) {
|
||||
samlUsers, err := self.GetSamlusers()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetLocalUserCloudroles")
|
||||
return nil, errors.Wrapf(err, "GetSamlusers")
|
||||
}
|
||||
if len(roles) > 0 {
|
||||
return &roles[0], nil
|
||||
ret := []SCloudrole{}
|
||||
roleIds := []string{}
|
||||
for i := range samlUsers {
|
||||
if samlUsers[i].OwnerId == userId {
|
||||
roles, err := self.GetLocalCloudroles(userId, samlUsers[i].CloudgroupId, spId, grouped)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetLocalUserCloudroles")
|
||||
}
|
||||
for i := range roles {
|
||||
if !utils.IsInStringArray(roles[i].Id, roleIds) {
|
||||
ret = append(ret, roles[i])
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(roles) == 0 {
|
||||
role := SCloudrole{}
|
||||
role.SetModelManager(CloudroleManager, &role)
|
||||
role.CloudaccountId = self.Id
|
||||
role.SAMLProviderId = spId
|
||||
if grouped {
|
||||
group, err := CloudgroupManager.FetchById(samlUsers[i].CloudgroupId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "CloudgroupManager.FetchById(%s)", samlUsers[i].CloudgroupId)
|
||||
}
|
||||
role.Name = stringutils2.GenerateRoleName(group.GetName())
|
||||
role.CloudgroupId = group.GetId()
|
||||
} else {
|
||||
user, err := db.UserCacheManager.FetchById(userId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "UserCacheManager.FetchById(%s)", userId)
|
||||
}
|
||||
role.Name = stringutils2.GenerateRoleName(user.GetName())
|
||||
role.OwnerId = userId
|
||||
}
|
||||
role.Status = api.CLOUD_ROLE_STATUS_CREATING
|
||||
role.DomainId = self.DomainId
|
||||
err = CloudroleManager.TableSpec().Insert(context.TODO(), &role)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Insert role")
|
||||
}
|
||||
ret = append(ret, role)
|
||||
}
|
||||
}
|
||||
}
|
||||
user, err := db.UserCacheManager.FetchById(userId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "UserCacheManager.FetchById(%s)", userId)
|
||||
}
|
||||
role := &SCloudrole{}
|
||||
role.SetModelManager(CloudroleManager, role)
|
||||
role.CloudaccountId = self.Id
|
||||
role.OwnerId = userId
|
||||
role.SAMLProviderId = spId
|
||||
role.Name = stringutils2.GenerateRoleName(user.GetName())
|
||||
role.Status = api.CLOUD_ROLE_STATUS_CREATING
|
||||
role.DomainId = self.DomainId
|
||||
return role, CloudroleManager.TableSpec().Insert(context.TODO(), role)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) GetCloudrole(userId string) (*SCloudrole, error) {
|
||||
func (self *SCloudaccount) getCloudrolesForSync(userId string, grouped bool) ([]SCloudrole, error) {
|
||||
sp, valid := self.IsSAMLProviderValid()
|
||||
if !valid {
|
||||
return nil, fmt.Errorf("SAMLProvider for account %s not ready", self.Id)
|
||||
}
|
||||
|
||||
return self.RegisterCloudrole(userId, sp.Id)
|
||||
return self.RegisterCloudroles(userId, grouped, sp.Id)
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) SyncRole(userId string) (*SCloudrole, error) {
|
||||
role, err := self.GetCloudrole(userId)
|
||||
func (self *SCloudaccount) SyncRoles(userId string, grouped bool) ([]SCloudrole, error) {
|
||||
roles, err := self.getCloudrolesForSync(userId, grouped)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetCloudrole")
|
||||
}
|
||||
|
||||
err = role.SyncRoles()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SyncRoles")
|
||||
for i := range roles {
|
||||
err = roles[i].SyncRoles()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SyncRoles")
|
||||
}
|
||||
}
|
||||
|
||||
return role, nil
|
||||
if len(roles) == 0 {
|
||||
return nil, fmt.Errorf("not found any available roles")
|
||||
}
|
||||
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) GetCloudroles() ([]SCloudrole, error) {
|
||||
roles := []SCloudrole{}
|
||||
q := CloudroleManager.Query()
|
||||
q := CloudroleManager.Query().Equals("cloudaccount_id", self.Id)
|
||||
err := db.FetchModelObjects(CloudroleManager, q, &roles)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
|
||||
@@ -41,6 +41,7 @@ type SCloudroleManager struct {
|
||||
db.SExternalizedResourceBaseManager
|
||||
SCloudaccountResourceBaseManager
|
||||
SAMLProviderResourceBaseManager
|
||||
SCloudgroupResourceBaseManager
|
||||
}
|
||||
|
||||
var CloudroleManager *SCloudroleManager
|
||||
@@ -62,6 +63,7 @@ type SCloudrole struct {
|
||||
db.SExternalizedResourceBase
|
||||
SCloudaccountResourceBase
|
||||
SAMLProviderResourceBase
|
||||
SCloudgroupResourceBase
|
||||
|
||||
Document *jsonutils.JSONDict `length:"long" charset:"ascii" list:"domain" update:"domain" create:"domain_required"`
|
||||
OwnerId string `width:"128" charset:"ascii" index:"true" list:"user" nullable:"false" create:"optional"`
|
||||
@@ -80,6 +82,11 @@ func (manager *SCloudroleManager) ListItemFilter(ctx context.Context, q *sqlchem
|
||||
return nil, err
|
||||
}
|
||||
|
||||
q, err = manager.SCloudgroupResourceBaseManager.ListItemFilter(ctx, q, userCred, query.CloudgroupResourceListInput)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
@@ -161,10 +168,13 @@ func (self *SCloudrole) GetICloudrole() (cloudprovider.ICloudrole, error) {
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetSAMLProvider")
|
||||
}
|
||||
for i := 0; i < 10; i++ {
|
||||
for {
|
||||
_, err := provider.GetICloudroleByName(self.Name)
|
||||
if err != nil && errors.Cause(err) == cloudprovider.ErrNotFound {
|
||||
break
|
||||
if err != nil {
|
||||
if errors.Cause(err) == cloudprovider.ErrNotFound {
|
||||
break
|
||||
}
|
||||
return nil, errors.Wrapf(err, "GetICloudroleByName(%s)", self.Name)
|
||||
}
|
||||
info := strings.Split(self.Name, "-")
|
||||
num, err := strconv.Atoi(info[len(info)-1])
|
||||
@@ -196,10 +206,16 @@ func (self *SCloudrole) GetICloudrole() (cloudprovider.ICloudrole, error) {
|
||||
|
||||
func (self *SCloudrole) GetCloudpolicies() ([]SCloudpolicy, error) {
|
||||
q := CloudpolicyManager.Query()
|
||||
samlUsers := SamluserManager.Query("cloudgroup_id").Equals("owner_id", self.OwnerId).Equals("cloudaccount_id", self.CloudaccountId).SubQuery()
|
||||
groups := CloudgroupManager.Query("id").In("id", samlUsers)
|
||||
gp := CloudgroupPolicyManager.Query("cloudpolicy_id").In("cloudgroup_id", groups).SubQuery()
|
||||
q = q.In("id", gp)
|
||||
var sq *sqlchemy.SSubQuery
|
||||
if len(self.OwnerId) > 0 {
|
||||
su := SamluserManager.Query("cloudgroup_id").Equals("owner_id", self.OwnerId).Equals("cloudaccount_id", self.CloudaccountId).SubQuery()
|
||||
sq = CloudgroupPolicyManager.Query("cloudpolicy_id").In("cloudgroup_id", su).SubQuery()
|
||||
} else if len(self.CloudgroupId) > 0 {
|
||||
sq = CloudgroupPolicyManager.Query("cloudpolicy_id").Equals("cloudgroup_id", self.CloudgroupId).SubQuery()
|
||||
} else {
|
||||
return nil, fmt.Errorf("empty owner id or cloudgroup id")
|
||||
}
|
||||
q = q.In("id", sq)
|
||||
policies := []SCloudpolicy{}
|
||||
err := db.FetchModelObjects(CloudpolicyManager, q, &policies)
|
||||
if err != nil {
|
||||
|
||||
@@ -127,16 +127,6 @@ func (manager *SSamluserManager) ValidateCreateData(ctx context.Context, userCre
|
||||
return input, err
|
||||
}
|
||||
group := _group.(*SCloudgroup)
|
||||
sq := CloudgroupManager.Query("id").Equals("provider", group.Provider).SubQuery()
|
||||
q := manager.Query().Equals("owner_id", input.OwnerId).In("cloudgroup_id", sq)
|
||||
groups := []SCloudgroup{}
|
||||
err = db.FetchModelObjects(CloudgroupManager, q, &groups)
|
||||
if err != nil {
|
||||
return input, httperrors.NewGeneralError(errors.Wrapf(err, "db.FetchModelObjects"))
|
||||
}
|
||||
if len(groups) > 0 {
|
||||
return input, httperrors.NewConflictError("user %s has already in other %s group", input.Name, group.Provider)
|
||||
}
|
||||
_account, err := validators.ValidateModel(userCred, CloudaccountManager, &input.CloudaccountId)
|
||||
if err != nil {
|
||||
return input, err
|
||||
@@ -148,6 +138,17 @@ func (manager *SSamluserManager) ValidateCreateData(ctx context.Context, userCre
|
||||
if account.Provider != group.Provider {
|
||||
return input, httperrors.NewConflictError("account %s and group %s not with same provider", account.Name, group.Name)
|
||||
}
|
||||
|
||||
sq := CloudgroupManager.Query("id").Equals("provider", group.Provider).SubQuery()
|
||||
q := manager.Query().Equals("owner_id", input.OwnerId).Equals("cloudaccount_id", account.Id).In("cloudgroup_id", sq)
|
||||
groups := []SCloudgroup{}
|
||||
err = db.FetchModelObjects(CloudgroupManager, q, &groups)
|
||||
if err != nil {
|
||||
return input, httperrors.NewGeneralError(errors.Wrapf(err, "db.FetchModelObjects"))
|
||||
}
|
||||
if len(groups) > 0 {
|
||||
return input, httperrors.NewConflictError("user %s has already in other %s group", input.Name, group.Provider)
|
||||
}
|
||||
input.Status = api.SAML_USER_STATUS_AVAILABLE
|
||||
return input, nil
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ func (d *SAliyunSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCr
|
||||
return data, httperrors.NewResourceNotReadyError("SAMLProvider for account %s not ready", account.Id)
|
||||
}
|
||||
|
||||
role, err := account.SyncRole(userCred.GetUserId())
|
||||
roles, err := account.SyncRoles(userCred.GetUserId(), true)
|
||||
if err != nil {
|
||||
return data, httperrors.NewGeneralError(errors.Wrapf(err, "SyncRole"))
|
||||
}
|
||||
@@ -61,7 +61,7 @@ func (d *SAliyunSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCr
|
||||
data.NameIdFormat = samlutils.NAME_ID_FORMAT_PERSISTENT
|
||||
data.AudienceRestriction = sp.GetEntityId()
|
||||
for k, v := range map[string]string{
|
||||
"https://www.aliyun.com/SAML-Role/Attributes/Role": fmt.Sprintf("%s,%s", role.ExternalId, SAMLProvider.ExternalId),
|
||||
"https://www.aliyun.com/SAML-Role/Attributes/Role": fmt.Sprintf("%s,%s", roles[0].ExternalId, SAMLProvider.ExternalId),
|
||||
"https://www.aliyun.com/SAML-Role/Attributes/RoleSessionName": userCred.GetUserId(),
|
||||
"https://www.aliyun.com/SAML-Role/Attributes/SessionDuration": "1800",
|
||||
} {
|
||||
|
||||
@@ -52,7 +52,7 @@ func (d *SAWSSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCred
|
||||
return data, httperrors.NewResourceNotReadyError("SAMLProvider for account %s not ready", account.Id)
|
||||
}
|
||||
|
||||
role, err := account.SyncRole(userCred.GetUserId())
|
||||
roles, err := account.SyncRoles(userCred.GetUserId(), true)
|
||||
if err != nil {
|
||||
return data, httperrors.NewGeneralError(errors.Wrapf(err, "SyncRole"))
|
||||
}
|
||||
@@ -68,7 +68,7 @@ func (d *SAWSSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCred
|
||||
{
|
||||
name: "https://aws.amazon.com/SAML/Attributes/Role",
|
||||
friendlyName: "RoleEntitlement",
|
||||
value: fmt.Sprintf("%s,%s", role.ExternalId, SAMLProvider.ExternalId),
|
||||
value: fmt.Sprintf("%s,%s", roles[0].ExternalId, SAMLProvider.ExternalId),
|
||||
},
|
||||
{
|
||||
name: "https://aws.amazon.com/SAML/Attributes/RoleSessionName",
|
||||
|
||||
@@ -51,7 +51,7 @@ func (d *SAWSCNSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCre
|
||||
return data, httperrors.NewResourceNotReadyError("SAMLProvider for account %s not ready", account.Id)
|
||||
}
|
||||
|
||||
role, err := account.SyncRole(userCred.GetUserId())
|
||||
roles, err := account.SyncRoles(userCred.GetUserId(), true)
|
||||
if err != nil {
|
||||
return data, httperrors.NewGeneralError(errors.Wrapf(err, "SyncRole"))
|
||||
}
|
||||
@@ -67,7 +67,7 @@ func (d *SAWSCNSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCre
|
||||
{
|
||||
name: "https://aws.amazon.com/SAML/Attributes/Role",
|
||||
friendlyName: "RoleEntitlement",
|
||||
value: fmt.Sprintf("%s,%s", role.ExternalId, SAMLProvider.ExternalId),
|
||||
value: fmt.Sprintf("%s,%s", roles[0].ExternalId, SAMLProvider.ExternalId),
|
||||
},
|
||||
{
|
||||
name: "https://aws.amazon.com/SAML/Attributes/RoleSessionName",
|
||||
|
||||
@@ -52,14 +52,14 @@ func (d *SQcloudSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCr
|
||||
return data, httperrors.NewResourceNotReadyError("SAMLProvider for account %s not ready", account.Id)
|
||||
}
|
||||
|
||||
role, err := account.SyncRole(userCred.GetUserId())
|
||||
roles, err := account.SyncRoles(userCred.GetUserId(), true)
|
||||
if err != nil {
|
||||
return data, httperrors.NewGeneralError(errors.Wrapf(err, "SyncRole"))
|
||||
}
|
||||
|
||||
roleStr := fmt.Sprintf("qcs::cam::uin/%s:roleName/%s,qcs::cam::uin/%s:saml-provider/%s", account.AccountId, role.ExternalId, account.AccountId, SAMLProvider.ExternalId)
|
||||
roleStr := fmt.Sprintf("qcs::cam::uin/%s:roleName/%s,qcs::cam::uin/%s:saml-provider/%s", account.AccountId, roles[0].ExternalId, account.AccountId, SAMLProvider.ExternalId)
|
||||
|
||||
data.NameId = role.Name
|
||||
data.NameId = roles[0].Name
|
||||
data.NameIdFormat = samlutils.NAME_ID_FORMAT_TRANSIENT
|
||||
data.AudienceRestriction = "https://cloud.tencent.com"
|
||||
for _, v := range []struct {
|
||||
@@ -75,7 +75,7 @@ func (d *SQcloudSAMLDriver) GetIdpInitiatedLoginData(ctx context.Context, userCr
|
||||
{
|
||||
name: "https://cloud.tencent.com/SAML/Attributes/RoleSessionName",
|
||||
friendlyName: "RoleSessionName",
|
||||
value: role.Name,
|
||||
value: roles[0].Name,
|
||||
},
|
||||
} {
|
||||
data.Attributes = append(data.Attributes, samlutils.SSAMLResponseAttribute{
|
||||
@@ -94,7 +94,7 @@ func (d *SQcloudSAMLDriver) GetSpInitiatedLoginData(ctx context.Context, userCre
|
||||
_account, err := models.CloudaccountManager.FetchById(cloudAccountId)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return data, httperrors.NewResourceNotFoundError("cloudaccount", cloudAccountId)
|
||||
return data, httperrors.NewResourceNotFoundError2("cloudaccount", cloudAccountId)
|
||||
}
|
||||
return data, httperrors.NewGeneralError(err)
|
||||
}
|
||||
@@ -111,14 +111,14 @@ func (d *SQcloudSAMLDriver) GetSpInitiatedLoginData(ctx context.Context, userCre
|
||||
return data, httperrors.NewResourceNotReadyError("SAMLProvider for account %s not ready", account.Id)
|
||||
}
|
||||
|
||||
role, err := account.SyncRole(userCred.GetUserId())
|
||||
roles, err := account.SyncRoles(userCred.GetUserId(), true)
|
||||
if err != nil {
|
||||
return data, httperrors.NewGeneralError(errors.Wrapf(err, "SyncRole"))
|
||||
}
|
||||
|
||||
roleStr := fmt.Sprintf("qcs::cam::uin/%s:roleName/%s,qcs::cam::uin/%s:saml-provider/%s", account.AccountId, role.ExternalId, account.AccountId, SAMLProvider.ExternalId)
|
||||
roleStr := fmt.Sprintf("qcs::cam::uin/%s:roleName/%s,qcs::cam::uin/%s:saml-provider/%s", account.AccountId, roles[0].ExternalId, account.AccountId, SAMLProvider.ExternalId)
|
||||
|
||||
data.NameId = role.Name
|
||||
data.NameId = roles[0].Name
|
||||
data.NameIdFormat = samlutils.NAME_ID_FORMAT_TRANSIENT
|
||||
data.AudienceRestriction = "https://cloud.tencent.com"
|
||||
for _, v := range []struct {
|
||||
@@ -134,7 +134,7 @@ func (d *SQcloudSAMLDriver) GetSpInitiatedLoginData(ctx context.Context, userCre
|
||||
{
|
||||
name: "https://cloud.tencent.com/SAML/Attributes/RoleSessionName",
|
||||
friendlyName: "RoleSessionName",
|
||||
value: role.Name,
|
||||
value: roles[0].Name,
|
||||
},
|
||||
} {
|
||||
data.Attributes = append(data.Attributes, samlutils.SSAMLResponseAttribute{
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
@@ -163,12 +162,6 @@ type ProviderConfig struct {
|
||||
ProxyFunc httputils.TransportProxyFunc
|
||||
}
|
||||
|
||||
func (cp *ProviderConfig) HttpClient() *http.Client {
|
||||
client := httputils.GetClient(true, 15*time.Second)
|
||||
httputils.SetClientProxyFunc(client, cp.ProxyFunc)
|
||||
return client
|
||||
}
|
||||
|
||||
func (cp *ProviderConfig) AdaptiveTimeoutHttpClient() *http.Client {
|
||||
client := httputils.GetAdaptiveTimeoutClient()
|
||||
httputils.SetClientProxyFunc(client, cp.ProxyFunc)
|
||||
|
||||
@@ -15,15 +15,71 @@
|
||||
package cloudprovider
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/fatih/set.v0"
|
||||
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
"yunion.io/x/pkg/utils"
|
||||
)
|
||||
|
||||
const DEFAULT_CLOUD_RULE_ID = "default_cloud_rule_id"
|
||||
const DEFAULT_LOCAL_RULE_ID = "default_local_rule_id"
|
||||
type SecDriver interface {
|
||||
GetDefaultSecurityGroupInRule() SecurityRule
|
||||
GetDefaultSecurityGroupOutRule() SecurityRule
|
||||
GetSecurityGroupRuleMaxPriority() int
|
||||
GetSecurityGroupRuleMinPriority() int
|
||||
IsOnlySupportAllowRules() bool
|
||||
IsSupportPeerSecgroup() bool
|
||||
}
|
||||
|
||||
func NewSecRuleInfo(driver SecDriver) SecRuleInfo {
|
||||
return SecRuleInfo{
|
||||
InDefaultRule: driver.GetDefaultSecurityGroupInRule(),
|
||||
OutDefaultRule: driver.GetDefaultSecurityGroupOutRule(),
|
||||
MinPriority: driver.GetSecurityGroupRuleMinPriority(),
|
||||
MaxPriority: driver.GetSecurityGroupRuleMaxPriority(),
|
||||
IsOnlySupportAllowRules: driver.IsOnlySupportAllowRules(),
|
||||
IsSupportPeerSecgroup: driver.IsSupportPeerSecgroup(),
|
||||
}
|
||||
}
|
||||
|
||||
const DEFAULT_DEST_RULE_ID = "default_dest_rule_id"
|
||||
const DEFAULT_SRC_RULE_ID = "default_src_rule_id"
|
||||
|
||||
type SecRuleInfo struct {
|
||||
InDefaultRule SecurityRule
|
||||
OutDefaultRule SecurityRule
|
||||
Rules SecurityRuleSet
|
||||
MinPriority int
|
||||
MaxPriority int
|
||||
IsOnlySupportAllowRules bool
|
||||
IsSupportPeerSecgroup bool
|
||||
}
|
||||
|
||||
func (r SecRuleInfo) AddDefaultRule(d SecRuleInfo, inRules, outRules []SecurityRule, isSrc bool) ([]SecurityRule, []SecurityRule) {
|
||||
min, max := r.MinPriority, r.MaxPriority
|
||||
r.InDefaultRule.Priority = min + 1
|
||||
r.OutDefaultRule.Priority = min + 1
|
||||
if max >= min {
|
||||
r.InDefaultRule.Priority = min - 1
|
||||
r.OutDefaultRule.Priority = min - 1
|
||||
}
|
||||
|
||||
if isSrc {
|
||||
r.InDefaultRule.Id = DEFAULT_SRC_RULE_ID
|
||||
r.OutDefaultRule.Id = DEFAULT_SRC_RULE_ID
|
||||
} else {
|
||||
r.InDefaultRule.ExternalId = DEFAULT_DEST_RULE_ID
|
||||
r.OutDefaultRule.ExternalId = DEFAULT_DEST_RULE_ID
|
||||
}
|
||||
|
||||
inRules = append(inRules, r.InDefaultRule)
|
||||
outRules = append(outRules, r.OutDefaultRule)
|
||||
return inRules, outRules
|
||||
}
|
||||
|
||||
type SecurityGroupFilterOptions struct {
|
||||
VpcId string
|
||||
@@ -43,57 +99,38 @@ type SecurityRule struct {
|
||||
secrules.SecurityRule
|
||||
Name string
|
||||
ExternalId string
|
||||
Id string
|
||||
|
||||
PeerSecgroupId string
|
||||
}
|
||||
|
||||
type LocalSecurityRule struct {
|
||||
secrules.SecurityRule
|
||||
ExternalId string
|
||||
}
|
||||
|
||||
func (r LocalSecurityRule) String() string {
|
||||
return r.SecurityRule.String()
|
||||
}
|
||||
|
||||
type LocalSecurityRuleSet []LocalSecurityRule
|
||||
|
||||
func (srs LocalSecurityRuleSet) Len() int {
|
||||
return len(srs)
|
||||
}
|
||||
|
||||
func (srs LocalSecurityRuleSet) Swap(i, j int) {
|
||||
srs[i], srs[j] = srs[j], srs[i]
|
||||
}
|
||||
|
||||
func (srs LocalSecurityRuleSet) Less(i, j int) bool {
|
||||
if srs[i].Priority > srs[j].Priority {
|
||||
return true
|
||||
} else if srs[i].Priority == srs[j].Priority {
|
||||
return srs[i].String() < srs[j].String()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (srs LocalSecurityRuleSet) AllowList() secrules.SecurityRuleSet {
|
||||
rules := secrules.SecurityRuleSet{}
|
||||
for _, r := range srs {
|
||||
rules = append(rules, r.SecurityRule)
|
||||
}
|
||||
return rules.AllowList()
|
||||
}
|
||||
|
||||
type TPriorityOrder int
|
||||
|
||||
var (
|
||||
PriorityOrderByDesc = TPriorityOrder(1)
|
||||
PriorityOrderByAsc = TPriorityOrder(-1)
|
||||
)
|
||||
|
||||
func (r SecurityRule) String() string {
|
||||
return r.SecurityRule.String()
|
||||
if len(r.PeerSecgroupId) == 0 {
|
||||
return r.SecurityRule.String()
|
||||
}
|
||||
return fmt.Sprintf("%s-%s", r.SecurityRule.String(), r.PeerSecgroupId)
|
||||
}
|
||||
|
||||
type SecurityRuleSet []SecurityRule
|
||||
|
||||
func (rules SecurityRuleSet) Split(isSupportPeerSecgroup bool) (in, out SecurityRuleSet, isStandardRules bool) {
|
||||
isStandardRules = true
|
||||
for i := 0; i < len(rules); i++ {
|
||||
if len(rules[i].PeerSecgroupId) > 0 {
|
||||
isStandardRules = false
|
||||
}
|
||||
if !isSupportPeerSecgroup && len(rules[i].PeerSecgroupId) > 0 {
|
||||
continue
|
||||
}
|
||||
if rules[i].Direction == secrules.DIR_IN {
|
||||
in = append(in, rules[i])
|
||||
} else {
|
||||
out = append(out, rules[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (srs SecurityRuleSet) Len() int {
|
||||
return len(srs)
|
||||
}
|
||||
@@ -114,234 +151,193 @@ func (srs SecurityRuleSet) AllowList() secrules.SecurityRuleSet {
|
||||
return rules.AllowList()
|
||||
}
|
||||
|
||||
func AddDefaultRule(rules []SecurityRule, defaultRule SecurityRule, localRuleStr string, order TPriorityOrder, min, max int, onlyAllowRules bool) []SecurityRule {
|
||||
if defaultRule.String() == localRuleStr {
|
||||
return rules
|
||||
func (srs SecurityRuleSet) Debug() {
|
||||
for i := 0; i < len(srs); i++ {
|
||||
log.Debugf("Name: %s id: %s external_id: %s priority: %d %s", srs[i].Name, srs[i].Id, srs[i].ExternalId, srs[i].Priority, srs[i].String())
|
||||
}
|
||||
defaultRule.ExternalId = DEFAULT_CLOUD_RULE_ID
|
||||
if order == PriorityOrderByDesc {
|
||||
defaultRule.Priority = min
|
||||
} else {
|
||||
defaultRule.Priority = max
|
||||
}
|
||||
defaultRule.Priority -= int(order)
|
||||
return append(rules, defaultRule)
|
||||
}
|
||||
|
||||
func SortSecurityRule(rules SecurityRuleSet, order TPriorityOrder, onlyAllowRules bool) {
|
||||
if onlyAllowRules {
|
||||
sort.Sort(rules)
|
||||
return
|
||||
}
|
||||
if order == PriorityOrderByAsc {
|
||||
func SortSecurityRule(rules SecurityRuleSet, max, min int, isAsc, onlyAllowRules bool) {
|
||||
if (max >= min || onlyAllowRules) && !isAsc {
|
||||
sort.Sort(sort.Reverse(rules))
|
||||
return
|
||||
}
|
||||
sort.Sort(rules)
|
||||
return
|
||||
}
|
||||
|
||||
func CompareRules(
|
||||
minPriority, maxPriority int, order TPriorityOrder,
|
||||
localRules secrules.SecurityRuleSet, remoteRules []SecurityRule,
|
||||
defaultInRule, defaultOutRule SecurityRule,
|
||||
onlyAllowRules bool, debug bool,
|
||||
) (common, inAdds, outAdds, inDels, outDels []SecurityRule) {
|
||||
localInRules := LocalSecurityRuleSet{}
|
||||
localOutRules := LocalSecurityRuleSet{}
|
||||
for i := range localRules {
|
||||
localRule := LocalSecurityRule{}
|
||||
localRule.SecurityRule = localRules[i]
|
||||
if localRules[i].Direction == secrules.DIR_IN {
|
||||
localInRules = append(localInRules, localRule)
|
||||
} else {
|
||||
localOutRules = append(localOutRules, localRule)
|
||||
func isAllowListEqual(src, dest secrules.SecurityRuleSet) bool {
|
||||
if len(src) != len(dest) {
|
||||
return false
|
||||
}
|
||||
s1, s2 := set.New(set.ThreadSafe), set.New(set.ThreadSafe)
|
||||
for i := 0; i < len(src); i++ {
|
||||
s1.Add(src[i].String())
|
||||
s2.Add(dest[i].String())
|
||||
}
|
||||
return s1.IsEqual(s2)
|
||||
}
|
||||
|
||||
func CompareRules(src, dest SecRuleInfo, debug bool) (common, inAdds, outAdds, inDels, outDels SecurityRuleSet) {
|
||||
srcInRules, srcOutRules, isSrcStandardRules := src.Rules.Split(src.IsSupportPeerSecgroup)
|
||||
destInRules, destOutRules, isDestStandardRules := dest.Rules.Split(dest.IsSupportPeerSecgroup)
|
||||
|
||||
srcInRules, srcOutRules = src.AddDefaultRule(dest, srcInRules, srcOutRules, true)
|
||||
destInRules, destOutRules = dest.AddDefaultRule(src, destInRules, destOutRules, false)
|
||||
|
||||
if debug {
|
||||
log.Debugf("src in rules: ")
|
||||
srcInRules.Debug()
|
||||
}
|
||||
|
||||
if (isSrcStandardRules && isDestStandardRules) || (!src.IsSupportPeerSecgroup && !dest.IsSupportPeerSecgroup) {
|
||||
// AllowList 需要优先级从高到低排序
|
||||
SortSecurityRule(srcInRules, src.MaxPriority, src.MinPriority, false, src.IsOnlySupportAllowRules)
|
||||
SortSecurityRule(srcOutRules, src.MaxPriority, src.MinPriority, false, src.IsOnlySupportAllowRules)
|
||||
|
||||
SortSecurityRule(destInRules, dest.MaxPriority, dest.MinPriority, false, dest.IsOnlySupportAllowRules)
|
||||
SortSecurityRule(destOutRules, dest.MaxPriority, dest.MinPriority, false, dest.IsOnlySupportAllowRules)
|
||||
|
||||
srcInAllowList := srcInRules.AllowList()
|
||||
srcOutAllowList := srcOutRules.AllowList()
|
||||
|
||||
destInAllowList := destInRules.AllowList()
|
||||
destOutAllowList := destOutRules.AllowList()
|
||||
inEquals, outEquals := isAllowListEqual(srcInAllowList, destInAllowList), isAllowListEqual(srcOutAllowList, destOutAllowList)
|
||||
|
||||
if inEquals && outEquals {
|
||||
return
|
||||
}
|
||||
}
|
||||
inRules := SecurityRuleSet{}
|
||||
outRules := SecurityRuleSet{}
|
||||
for i := 0; i < len(remoteRules); i++ {
|
||||
if remoteRules[i].Direction == secrules.DIR_IN {
|
||||
inRules = append(inRules, remoteRules[i])
|
||||
} else {
|
||||
outRules = append(outRules, remoteRules[i])
|
||||
|
||||
if debug {
|
||||
log.Debugf("In: src: %s dest: %s result: %v", srcInAllowList.String(), destInAllowList.String(), inEquals)
|
||||
log.Debugf("Out: src: %s dest: %s result: %v", srcOutAllowList.String(), destOutAllowList.String(), outEquals)
|
||||
}
|
||||
}
|
||||
var inCommon, outCommon = inRules, outRules
|
||||
|
||||
defaultLocalInRule := LocalSecurityRule{ExternalId: DEFAULT_LOCAL_RULE_ID}
|
||||
defaultLocalInRule.SecurityRule = *secrules.MustParseSecurityRule("in:deny any")
|
||||
defaultLocalOutRule := LocalSecurityRule{ExternalId: DEFAULT_LOCAL_RULE_ID}
|
||||
defaultLocalOutRule.SecurityRule = *secrules.MustParseSecurityRule("out:allow any")
|
||||
|
||||
inRules = AddDefaultRule(inRules, defaultInRule, defaultLocalInRule.String(), order, minPriority, maxPriority, onlyAllowRules)
|
||||
outRules = AddDefaultRule(outRules, defaultOutRule, defaultLocalOutRule.String(), order, minPriority, maxPriority, onlyAllowRules)
|
||||
|
||||
defaultInEquals, defaultOutEquals := true, true
|
||||
if defaultLocalInRule.String() != defaultInRule.String() {
|
||||
localInRules = append(localInRules, defaultLocalInRule)
|
||||
defaultInEquals = false
|
||||
}
|
||||
if defaultLocalOutRule.String() != defaultOutRule.String() {
|
||||
localOutRules = append(localOutRules, defaultLocalOutRule)
|
||||
defaultOutEquals = false
|
||||
}
|
||||
|
||||
sort.Sort(localInRules)
|
||||
sort.Sort(localOutRules)
|
||||
|
||||
localInAllowList := localInRules.AllowList()
|
||||
localOutAllowList := localOutRules.AllowList()
|
||||
_localInRules := LocalSecurityRuleSet{}
|
||||
for i := range localInAllowList {
|
||||
rule := LocalSecurityRule{}
|
||||
rule.SecurityRule = localInAllowList[i]
|
||||
_localInRules = append(_localInRules, rule)
|
||||
}
|
||||
_localOutRules := LocalSecurityRuleSet{}
|
||||
for i := range localOutAllowList {
|
||||
rule := LocalSecurityRule{}
|
||||
rule.SecurityRule = localOutAllowList[i]
|
||||
_localOutRules = append(_localOutRules, rule)
|
||||
}
|
||||
if onlyAllowRules {
|
||||
localOutRules, localInRules = _localOutRules, _localInRules
|
||||
}
|
||||
if len(_localInRules) < len(localInRules) {
|
||||
localInRules = _localInRules
|
||||
}
|
||||
if len(_localOutRules) < len(localOutRules) {
|
||||
localOutRules = _localOutRules
|
||||
}
|
||||
|
||||
SortSecurityRule(inRules, order, onlyAllowRules)
|
||||
SortSecurityRule(outRules, order, onlyAllowRules)
|
||||
|
||||
inAllowList := inRules.AllowList()
|
||||
outAllowList := outRules.AllowList()
|
||||
inEquals, outEquals := inAllowList.Equals(localInAllowList), outAllowList.Equals(localOutAllowList)
|
||||
if inEquals && outEquals {
|
||||
return
|
||||
}
|
||||
|
||||
// priority从小到大排列(从默认规则开始对比)
|
||||
sort.Sort(sort.Reverse(localInRules))
|
||||
sort.Sort(sort.Reverse(localOutRules))
|
||||
|
||||
sort.Sort(sort.Reverse(inRules))
|
||||
sort.Sort(sort.Reverse(outRules))
|
||||
|
||||
startPriority := minPriority - 1
|
||||
if order == PriorityOrderByAsc {
|
||||
startPriority = maxPriority + 1
|
||||
}
|
||||
|
||||
var addPriority = func(priority int, order TPriorityOrder, inc int, min, max int, onlyAllowRules bool) int {
|
||||
if onlyAllowRules {
|
||||
return 0
|
||||
}
|
||||
inc = inc * int(order) //+ int(order)
|
||||
priority += inc
|
||||
if priority < min {
|
||||
return min
|
||||
}
|
||||
if priority > max {
|
||||
return max
|
||||
}
|
||||
return priority
|
||||
}
|
||||
|
||||
var getInitPriority = func(init, min, max int) int {
|
||||
if init < min || init > max {
|
||||
return (min + max) / 2
|
||||
}
|
||||
return init
|
||||
}
|
||||
|
||||
var compare = func(localRules LocalSecurityRuleSet, remoteRules SecurityRuleSet) (common, add, del []SecurityRule) {
|
||||
i, j, inc, prePriority := 0, 0, 1, 0
|
||||
for i < len(localRules) || j < len(remoteRules) {
|
||||
if i < len(localRules) && j < len(remoteRules) {
|
||||
ruleStr := remoteRules[j].String()
|
||||
localRuleStr := localRules[i].String()
|
||||
if debug {
|
||||
log.Debugf("compare local priority(%d) %s -> remote name(%s) priority(%d) %s\n", localRules[i].Priority, localRules[i].String(), remoteRules[j].Name, remoteRules[j].Priority, remoteRules[j].String())
|
||||
var tryUseAllowList = func(defaultRule SecurityRule, allowList secrules.SecurityRuleSet, rules SecurityRuleSet, isOnlyAllowList bool) SecurityRuleSet {
|
||||
if len(allowList) < len(rules) || isOnlyAllowList {
|
||||
rules = SecurityRuleSet{}
|
||||
for i := range allowList {
|
||||
rule := SecurityRule{}
|
||||
rule.SecurityRule = allowList[i]
|
||||
rules = append(rules, rule)
|
||||
}
|
||||
cmp := strings.Compare(ruleStr, localRuleStr)
|
||||
|
||||
if !utils.IsInStringArray(allowList.String(), []string{
|
||||
"",
|
||||
"in:allow any",
|
||||
"out:allow any",
|
||||
"in:deny any",
|
||||
"out:deny any",
|
||||
}) && strings.HasSuffix(defaultRule.SecurityRule.String(), "deny any") {
|
||||
rules = append(rules, defaultRule)
|
||||
}
|
||||
}
|
||||
return rules
|
||||
}
|
||||
|
||||
srcInRules = tryUseAllowList(src.InDefaultRule, srcInAllowList, srcInRules, dest.IsOnlySupportAllowRules)
|
||||
srcOutRules = tryUseAllowList(src.OutDefaultRule, srcOutAllowList, srcOutRules, dest.IsOnlySupportAllowRules)
|
||||
|
||||
if inEquals {
|
||||
srcInRules, destInRules = []SecurityRule{}, []SecurityRule{}
|
||||
}
|
||||
if outEquals {
|
||||
srcOutRules, destOutRules = []SecurityRule{}, []SecurityRule{}
|
||||
}
|
||||
}
|
||||
|
||||
if debug {
|
||||
log.Debugf("src in rules: ")
|
||||
srcInRules.Debug()
|
||||
}
|
||||
|
||||
// 默认从优先级低到高比较
|
||||
SortSecurityRule(srcInRules, src.MaxPriority, src.MinPriority, true, src.IsOnlySupportAllowRules)
|
||||
SortSecurityRule(srcOutRules, src.MaxPriority, src.MinPriority, true, src.IsOnlySupportAllowRules)
|
||||
|
||||
SortSecurityRule(destInRules, dest.MaxPriority, dest.MinPriority, true, dest.IsOnlySupportAllowRules)
|
||||
SortSecurityRule(destOutRules, dest.MaxPriority, dest.MinPriority, true, dest.IsOnlySupportAllowRules)
|
||||
|
||||
var addPriority = func(priority int, min, max int, onlyAllowRules bool) int {
|
||||
if onlyAllowRules {
|
||||
return priority
|
||||
}
|
||||
inc := 1
|
||||
if max < min {
|
||||
max, min, inc = min, max, -1
|
||||
}
|
||||
if priority >= max || priority <= min {
|
||||
return priority
|
||||
}
|
||||
return priority + inc
|
||||
}
|
||||
|
||||
var _compare = func(srcRules SecurityRuleSet, destRules SecurityRuleSet) (common, add, del SecurityRuleSet) {
|
||||
i, j, priority := 0, 0, (dest.MinPriority-1+dest.MaxPriority)/2
|
||||
for i < len(srcRules) || j < len(destRules) {
|
||||
if i < len(srcRules) && j < len(destRules) {
|
||||
destRuleStr := destRules[j].String()
|
||||
srcRuleStr := srcRules[i].String()
|
||||
if debug {
|
||||
log.Debugf("compare src %s(%s) priority(%d) %s -> dest name(%s) %s(%s) priority(%d) %s\n",
|
||||
srcRules[i].Id, srcRules[i].ExternalId, srcRules[i].Priority, srcRules[i].String(),
|
||||
destRules[j].Name, destRules[j].ExternalId, destRules[j].Id, destRules[j].Priority, destRules[j].String())
|
||||
}
|
||||
cmp := strings.Compare(destRuleStr, srcRuleStr)
|
||||
if cmp == 0 {
|
||||
prePriority = remoteRules[j].Priority
|
||||
if remoteRules[j].ExternalId == DEFAULT_CLOUD_RULE_ID {
|
||||
remoteRules[j].Priority = addPriority(remoteRules[j].Priority, order, 1, minPriority, maxPriority, onlyAllowRules)
|
||||
}
|
||||
if localRules[i].ExternalId != DEFAULT_LOCAL_RULE_ID ||
|
||||
(localRules[i].Direction == secrules.DIR_IN && !defaultInEquals) ||
|
||||
(localRules[i].Direction == secrules.DIR_OUT && !defaultOutEquals) {
|
||||
common = append(common, remoteRules[j])
|
||||
destRules[j].Id = srcRules[i].Id
|
||||
common = append(common, destRules[j])
|
||||
if destRules[j].ExternalId != DEFAULT_DEST_RULE_ID {
|
||||
priority = destRules[j].Priority
|
||||
}
|
||||
i++
|
||||
j++
|
||||
} else if cmp < 0 {
|
||||
if remoteRules[j].ExternalId != DEFAULT_CLOUD_RULE_ID {
|
||||
del = append(del, remoteRules[j])
|
||||
}
|
||||
del = append(del, destRules[j])
|
||||
j++
|
||||
} else {
|
||||
initPriority := getInitPriority(prePriority, minPriority, maxPriority)
|
||||
localRules[i].Priority = addPriority(initPriority, order, inc, minPriority, maxPriority, onlyAllowRules)
|
||||
if localRules[i].ExternalId != DEFAULT_LOCAL_RULE_ID ||
|
||||
(localRules[i].Direction == secrules.DIR_IN && !defaultInEquals) ||
|
||||
(localRules[i].Direction == secrules.DIR_OUT && !defaultOutEquals) {
|
||||
add = append(add, SecurityRule{SecurityRule: localRules[i].SecurityRule})
|
||||
}
|
||||
priority = addPriority(priority, dest.MinPriority, dest.MaxPriority, dest.IsOnlySupportAllowRules)
|
||||
srcRules[i].Priority = priority
|
||||
add = append(add, srcRules[i])
|
||||
i++
|
||||
inc++
|
||||
}
|
||||
} else if i >= len(localRules) {
|
||||
if remoteRules[j].ExternalId != DEFAULT_CLOUD_RULE_ID {
|
||||
del = append(del, remoteRules[j])
|
||||
}
|
||||
} else if i >= len(srcRules) {
|
||||
del = append(del, destRules[j])
|
||||
j++
|
||||
} else if j >= len(remoteRules) {
|
||||
initPriority := startPriority
|
||||
if len(remoteRules) > 0 {
|
||||
initPriority = remoteRules[len(remoteRules)-1].Priority
|
||||
}
|
||||
initPriority = getInitPriority(initPriority, minPriority, maxPriority) // 若是初始添加规则,尽量以中间为节点,避免仅出现天地规则
|
||||
localRules[i].Priority = addPriority(initPriority, order, inc, minPriority, maxPriority, onlyAllowRules)
|
||||
if localRules[i].ExternalId != DEFAULT_LOCAL_RULE_ID ||
|
||||
(localRules[i].Direction == secrules.DIR_IN && !defaultInEquals) ||
|
||||
(localRules[i].Direction == secrules.DIR_OUT && !defaultOutEquals) {
|
||||
add = append(add, SecurityRule{SecurityRule: localRules[i].SecurityRule})
|
||||
}
|
||||
} else if j >= len(destRules) {
|
||||
priority = addPriority(priority, dest.MinPriority, dest.MaxPriority, dest.IsOnlySupportAllowRules)
|
||||
srcRules[i].Priority = priority
|
||||
add = append(add, srcRules[i])
|
||||
i++
|
||||
inc++
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type rulePair struct {
|
||||
localRules LocalSecurityRuleSet
|
||||
remoteRules []SecurityRule
|
||||
protocol string
|
||||
srcRules SecurityRuleSet
|
||||
destRules SecurityRuleSet
|
||||
protocol string
|
||||
}
|
||||
|
||||
var splitRules = func(localRules LocalSecurityRuleSet, remoteRules []SecurityRule) []rulePair {
|
||||
var splitRules = func(src, dest SecurityRuleSet) []rulePair {
|
||||
rules := map[string]rulePair{}
|
||||
for _, r := range localRules {
|
||||
for _, r := range src {
|
||||
pair, ok := rules[r.Protocol]
|
||||
if !ok {
|
||||
pair = rulePair{localRules: LocalSecurityRuleSet{}, remoteRules: []SecurityRule{}, protocol: r.Protocol}
|
||||
pair = rulePair{srcRules: SecurityRuleSet{}, destRules: SecurityRuleSet{}, protocol: r.Protocol}
|
||||
}
|
||||
pair.localRules = append(pair.localRules, r)
|
||||
pair.srcRules = append(pair.srcRules, r)
|
||||
rules[r.Protocol] = pair
|
||||
}
|
||||
|
||||
for _, r := range remoteRules {
|
||||
for _, r := range dest {
|
||||
pair, ok := rules[r.Protocol]
|
||||
if !ok {
|
||||
pair = rulePair{localRules: LocalSecurityRuleSet{}, remoteRules: []SecurityRule{}, protocol: r.Protocol}
|
||||
pair = rulePair{srcRules: SecurityRuleSet{}, destRules: SecurityRuleSet{}, protocol: r.Protocol}
|
||||
}
|
||||
pair.remoteRules = append(pair.remoteRules, r)
|
||||
pair.destRules = append(pair.destRules, r)
|
||||
rules[r.Protocol] = pair
|
||||
}
|
||||
|
||||
@@ -352,24 +348,62 @@ func CompareRules(
|
||||
return ret
|
||||
}
|
||||
|
||||
var compareRules = func(localRules LocalSecurityRuleSet, remoteRules []SecurityRule) (common, add, dels []SecurityRule) {
|
||||
pairs := splitRules(localRules, remoteRules)
|
||||
var compare = func(src, dest SecurityRuleSet) (common, added, dels SecurityRuleSet) {
|
||||
pairs := splitRules(src, dest)
|
||||
for _, r := range pairs {
|
||||
_common, _add, _dels := compare(r.localRules, r.remoteRules)
|
||||
_common, _add, _dels := _compare(r.srcRules, r.destRules)
|
||||
common = append(common, _common...)
|
||||
add = append(add, _add...)
|
||||
added = append(added, _add...)
|
||||
dels = append(dels, _dels...)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if !inEquals {
|
||||
inCommon, inAdds, inDels = compareRules(localInRules, inRules)
|
||||
var inCommon, outCommon SecurityRuleSet
|
||||
inCommon, inAdds, inDels = compare(srcInRules, destInRules)
|
||||
outCommon, outAdds, outDels = compare(srcOutRules, destOutRules)
|
||||
|
||||
var handleDefaultRules = func(removed, added []SecurityRule, isOnlyAllowList bool) ([]SecurityRule, []SecurityRule) {
|
||||
ret := []SecurityRule{}
|
||||
for _, rule := range removed {
|
||||
if rule.ExternalId == DEFAULT_DEST_RULE_ID {
|
||||
if debug {
|
||||
log.Debugf("remove dest default rule: %s external id %s priority: %d", rule.String(), rule.ExternalId, rule.Priority)
|
||||
}
|
||||
if rule.Action == secrules.SecurityRuleDeny && isOnlyAllowList {
|
||||
continue
|
||||
}
|
||||
switch rule.Action {
|
||||
case secrules.SecurityRuleDeny:
|
||||
rule.Action = secrules.SecurityRuleAllow
|
||||
case secrules.SecurityRuleAllow:
|
||||
rule.Action = secrules.SecurityRuleDeny
|
||||
}
|
||||
rule.Priority = dest.MinPriority
|
||||
|
||||
find := false
|
||||
for i := range added {
|
||||
if added[i].String() == rule.String() {
|
||||
find = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !find {
|
||||
if debug {
|
||||
log.Debugf("add new default rule: %s external id %s priority: %d", rule.String(), rule.ExternalId, rule.Priority)
|
||||
}
|
||||
added = append(added, rule)
|
||||
}
|
||||
} else {
|
||||
ret = append(ret, rule)
|
||||
}
|
||||
}
|
||||
return ret, added
|
||||
}
|
||||
if !outEquals {
|
||||
outCommon, outAdds, outDels = compareRules(localOutRules, outRules)
|
||||
}
|
||||
common = append(inCommon, outCommon...)
|
||||
|
||||
inDels, inAdds = handleDefaultRules(inDels, inAdds, dest.IsOnlySupportAllowRules)
|
||||
outDels, outAdds = handleDefaultRules(outDels, outAdds, dest.IsOnlySupportAllowRules)
|
||||
common, _ = handleDefaultRules(append(inCommon, outCommon...), []SecurityRule{}, dest.IsOnlySupportAllowRules)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/cmdline"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/baremetal"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
@@ -291,7 +292,14 @@ func (self *SKVMHostDriver) RequestDeallocateDiskOnHost(ctx context.Context, hos
|
||||
url := fmt.Sprintf("/disks/%s/delete/%s", storage.Id, disk.Id)
|
||||
body := jsonutils.NewDict()
|
||||
_, err := host.Request(ctx, task.GetUserCred(), "POST", url, header, body)
|
||||
return err
|
||||
if err != nil {
|
||||
if errors.Cause(err) == cloudprovider.ErrNotFound {
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (driver *SKVMHostDriver) RequestDeallocateBackupDiskOnHost(ctx context.Context, host *models.SHost, storage *models.SStorage, disk *models.SDisk, task taskman.ITask) error {
|
||||
|
||||
@@ -1690,13 +1690,30 @@ type SBucketUsages struct {
|
||||
func (manager *SBucketManager) TotalCount(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, rangeObjs []db.IStandaloneModel, providers []string, brands []string, cloudEnv string) SBucketUsages {
|
||||
usage := SBucketUsages{}
|
||||
buckets := manager.Query().SubQuery()
|
||||
bucketsQ := buckets.Query(
|
||||
sqlchemy.NewFunction(
|
||||
sqlchemy.NewCase().When(
|
||||
sqlchemy.GE(buckets.Field("object_cnt"), 0),
|
||||
buckets.Field("object_cnt"),
|
||||
).Else(sqlchemy.NewConstField(0)),
|
||||
"object_cnt1",
|
||||
),
|
||||
sqlchemy.NewFunction(
|
||||
sqlchemy.NewCase().When(
|
||||
sqlchemy.GE(buckets.Field("size_bytes"), 0),
|
||||
buckets.Field("size_bytes"),
|
||||
).Else(sqlchemy.NewConstField(0)),
|
||||
"size_bytes1",
|
||||
),
|
||||
)
|
||||
bucketsQ = manager.usageQ(bucketsQ, rangeObjs, providers, brands, cloudEnv)
|
||||
bucketsQ = scopeOwnerIdFilter(bucketsQ, scope, ownerId)
|
||||
buckets = bucketsQ.SubQuery()
|
||||
q := buckets.Query(
|
||||
sqlchemy.COUNT("buckets"),
|
||||
sqlchemy.SUM("objects", buckets.Field("object_cnt")),
|
||||
sqlchemy.SUM("bytes", buckets.Field("size_bytes")),
|
||||
sqlchemy.SUM("objects", buckets.Field("object_cnt1")),
|
||||
sqlchemy.SUM("bytes", buckets.Field("size_bytes1")),
|
||||
)
|
||||
q = manager.usageQ(q, rangeObjs, providers, brands, cloudEnv)
|
||||
q = scopeOwnerIdFilter(q, scope, ownerId)
|
||||
err := q.First(&usage)
|
||||
if err != nil {
|
||||
log.Errorf("Query bucket usage error %s", err)
|
||||
|
||||
@@ -359,7 +359,8 @@ func (scm *SCloudaccountManager) AllowPerformPrepareNets(_ context.Context, user
|
||||
|
||||
type sNetworkInfo struct {
|
||||
esxi.SNetworkInfo
|
||||
prefix string
|
||||
prefix string
|
||||
fakeVsId string
|
||||
}
|
||||
|
||||
func (scm *SCloudaccountManager) hostVMIPsPrepareNets(ctx context.Context, client *esxi.SESXiClient,
|
||||
@@ -376,9 +377,11 @@ func (scm *SCloudaccountManager) hostVMIPsPrepareNets(ctx context.Context, clien
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to fetch ips of hosts and vms")
|
||||
}
|
||||
nInfo.IPPool.FillVsId(caName)
|
||||
ret = append(ret, sNetworkInfo{
|
||||
SNetworkInfo: nInfo,
|
||||
prefix: caName,
|
||||
fakeVsId: caName,
|
||||
})
|
||||
case api.CLOUD_ACCOUNT_WIRE_LEVEL_DATACENTER:
|
||||
dcs, err := client.GetDatacenters()
|
||||
@@ -390,9 +393,12 @@ func (scm *SCloudaccountManager) hostVMIPsPrepareNets(ctx context.Context, clien
|
||||
if err != nil {
|
||||
return ret, errors.Wrapf(err, "unable to fetch ips of hosts and vms for dc %q", dc.GetName())
|
||||
}
|
||||
prefix := fmt.Sprintf("%s/%s", caName, dc.GetName())
|
||||
nInfo.IPPool.FillVsId(prefix)
|
||||
ret = append(ret, sNetworkInfo{
|
||||
SNetworkInfo: nInfo,
|
||||
prefix: fmt.Sprintf("%s/%s", caName, dc.GetName()),
|
||||
prefix: prefix,
|
||||
fakeVsId: prefix,
|
||||
})
|
||||
}
|
||||
case api.CLOUD_ACCOUNT_WIRE_LEVEL_CLUSTER:
|
||||
@@ -410,9 +416,12 @@ func (scm *SCloudaccountManager) hostVMIPsPrepareNets(ctx context.Context, clien
|
||||
if err != nil {
|
||||
return ret, errors.Wrapf(err, "unable to fetch ips of hosts and vms for dc %q cluster %q", dc.GetName(), cluster.GetName())
|
||||
}
|
||||
prefix := fmt.Sprintf("%s/%s/%s", caName, dc.GetName(), cluster.GetName())
|
||||
nInfo.IPPool.FillVsId(prefix)
|
||||
ret = append(ret, sNetworkInfo{
|
||||
SNetworkInfo: nInfo,
|
||||
prefix: fmt.Sprintf("%s/%s/%s", caName, dc.GetName(), cluster.GetName()),
|
||||
prefix: prefix,
|
||||
fakeVsId: prefix,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -555,6 +564,33 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
|
||||
wires = params.Wires
|
||||
networks = params.Networks
|
||||
)
|
||||
// build global existedNetMap and IPPool
|
||||
netNum := 0
|
||||
for i := range networks {
|
||||
netNum += len(networks[i])
|
||||
}
|
||||
existedNets := newIPPool(netNum)
|
||||
for _, nets := range networks {
|
||||
for i := range nets {
|
||||
startIp, _ := netutils.NewIPV4Addr(nets[i].GuestIpStart)
|
||||
endIp, _ := netutils.NewIPV4Addr(nets[i].GuestIpEnd)
|
||||
existedNets.Insert(startIp, sSimpleNet{
|
||||
Diff: endIp - startIp,
|
||||
Vlan: int32(nets[i].VlanId),
|
||||
Id: nets[i].Id,
|
||||
WireId: nets[i].WireId,
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
ipPoolLen := 0
|
||||
for i := range nInfos {
|
||||
ipPoolLen += nInfos[i].IPPool.Len()
|
||||
}
|
||||
ipPool := esxi.NewIPPool(ipPoolLen)
|
||||
for i := range nInfos {
|
||||
ipPool.Merge(&nInfos[i].IPPool)
|
||||
}
|
||||
output.CAWireNets = make([]api.CAWireNet, 0, len(nInfos))
|
||||
for _, ni := range nInfos {
|
||||
var (
|
||||
@@ -569,11 +605,10 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
|
||||
}
|
||||
// Find suitable wire and the network containing the Host IP in suitable wire.
|
||||
var (
|
||||
tmpSocre int
|
||||
maxScore = len(ipHosts)
|
||||
suitableWire *SWire
|
||||
suitableWireIndex = -1
|
||||
suitableNetworks map[netutils.IPV4Addr]*SNetwork
|
||||
tmpSocre int
|
||||
maxScore = len(ipHosts)
|
||||
suitableWire *SWire
|
||||
suitableNetworks map[netutils.IPV4Addr]*SNetwork
|
||||
)
|
||||
for i, nets := range networks {
|
||||
score := 0
|
||||
@@ -595,7 +630,6 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
|
||||
if score > tmpSocre {
|
||||
tmpSocre = score
|
||||
suitableWire = &wires[i]
|
||||
suitableWireIndex = i
|
||||
suitableNetworks = tmpSNs
|
||||
}
|
||||
if tmpSocre == maxScore {
|
||||
@@ -638,30 +672,12 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
|
||||
}
|
||||
|
||||
// Find the suitable network containing the VM IP, and if not, give the corresponding suggested network configuration in this project.
|
||||
var allNets []SNetwork
|
||||
if suitableWire != nil {
|
||||
allNets = networks[suitableWireIndex]
|
||||
}
|
||||
type simpleNet struct {
|
||||
Id string
|
||||
Vlan int32
|
||||
}
|
||||
existedNetMap := make(map[netutils.IPV4Addr]simpleNet, len(allNets))
|
||||
for i := range allNets {
|
||||
ipStart, _ := netutils.NewIPV4Addr(allNets[i].GuestIpStart)
|
||||
ipEnd, _ := netutils.NewIPV4Addr(allNets[i].GuestIpEnd)
|
||||
for ip := ipStart; ip <= ipEnd; ip++ {
|
||||
existedNetMap[ip] = simpleNet{Id: allNets[i].Id, Vlan: int32(allNets[i].VlanId)}
|
||||
}
|
||||
}
|
||||
|
||||
for i := range wireNet.HostSuggestedNetworks {
|
||||
ipStart, _ := netutils.NewIPV4Addr(wireNet.HostSuggestedNetworks[i].GuestIpStart)
|
||||
ipEnd, _ := netutils.NewIPV4Addr(wireNet.HostSuggestedNetworks[i].GuestIpEnd)
|
||||
existedNetMap[ipStart] = simpleNet{}
|
||||
if ipEnd != ipStart {
|
||||
existedNetMap[ipEnd] = simpleNet{}
|
||||
}
|
||||
existedNets.Insert(ipStart, sSimpleNet{
|
||||
Diff: ipEnd - ipStart,
|
||||
})
|
||||
}
|
||||
|
||||
guests := make([]api.CAGuestNet, len(ni.VMs))
|
||||
@@ -669,7 +685,7 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
|
||||
guests[i].Name = ni.VMs[i].Name
|
||||
for _, ipvlan := range ni.VMs[i].IPVlans {
|
||||
var suitableNetId string
|
||||
sn, ok := existedNetMap[ipvlan.IP]
|
||||
sn, ok := existedNets.Get(ipvlan.IP)
|
||||
if ok {
|
||||
suitableNetId = sn.Id
|
||||
}
|
||||
@@ -685,7 +701,7 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
|
||||
for vlan, ips := range ni.VlanIps {
|
||||
for i := 0; i < len(ips); i++ {
|
||||
ip := ips[i]
|
||||
if _, ok := existedNetMap[ip]; ok {
|
||||
if _, ok := existedNets.Get(ip); ok {
|
||||
continue
|
||||
}
|
||||
net := ip.NetAddr(24)
|
||||
@@ -694,20 +710,20 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
|
||||
// find startip
|
||||
startIp := ip - 1
|
||||
for ; startIp >= netLimitLow; startIp-- {
|
||||
if _, ok := existedNetMap[startIp]; ok {
|
||||
if _, ok := existedNets.Get(startIp); ok {
|
||||
break
|
||||
}
|
||||
if _, ok := ni.IPPool.Get(startIp); ok {
|
||||
if _, ok := ipPool.Get(startIp); ok {
|
||||
break
|
||||
}
|
||||
}
|
||||
endIp := ip + 1
|
||||
for ; endIp <= netLimitUp; endIp++ {
|
||||
if _, ok := existedNetMap[endIp]; ok {
|
||||
if _, ok := existedNets.Get(endIp); ok {
|
||||
break
|
||||
}
|
||||
if proc, ok := ni.IPPool.Get(endIp); ok {
|
||||
if proc.VlanId == vlan {
|
||||
if proc, ok := ipPool.Get(endIp); ok {
|
||||
if proc.VlanId == vlan && proc.VSId == ni.fakeVsId {
|
||||
// find one in ips
|
||||
i++
|
||||
continue
|
||||
@@ -729,8 +745,9 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
|
||||
},
|
||||
})
|
||||
// Avoid assigning already assigned ip subnet
|
||||
existedNetMap[startIp+1] = simpleNet{}
|
||||
existedNetMap[endIp-1] = simpleNet{}
|
||||
existedNets.Insert(startIp+1, sSimpleNet{
|
||||
Diff: endIp - startIp - 2,
|
||||
})
|
||||
}
|
||||
}
|
||||
output.CAWireNets = append(output.CAWireNets, wireNet)
|
||||
@@ -824,6 +841,64 @@ func (manager *SCloudaccountManager) suggestHostNetworks(ips []netutils.IPV4Addr
|
||||
return ret
|
||||
}
|
||||
|
||||
type sIPPool struct {
|
||||
netranges []netutils.IPV4Addr
|
||||
simpleNetMap map[netutils.IPV4Addr]sSimpleNet
|
||||
}
|
||||
|
||||
func newIPPool(length ...int) *sIPPool {
|
||||
initLen := 0
|
||||
if len(length) > 0 {
|
||||
initLen = length[0]
|
||||
}
|
||||
return &sIPPool{
|
||||
netranges: make([]netutils.IPV4Addr, 0, initLen),
|
||||
simpleNetMap: make(map[netutils.IPV4Addr]sSimpleNet, initLen),
|
||||
}
|
||||
}
|
||||
|
||||
type sSimpleNet struct {
|
||||
Diff netutils.IPV4Addr
|
||||
Id string
|
||||
Vlan int32
|
||||
WireId string
|
||||
}
|
||||
|
||||
func (pl *sIPPool) Insert(startIp netutils.IPV4Addr, sNet sSimpleNet) {
|
||||
// TODO:check
|
||||
index := pl.getIndex(startIp)
|
||||
pl.netranges = append(pl.netranges, 0)
|
||||
pl.netranges = append(pl.netranges[:index+1], pl.netranges[index:len(pl.netranges)-1]...)
|
||||
pl.netranges[index] = startIp
|
||||
pl.simpleNetMap[startIp] = sNet
|
||||
}
|
||||
|
||||
func (pl *sIPPool) getIndex(ip netutils.IPV4Addr) int {
|
||||
index := sort.Search(len(pl.netranges), func(n int) bool {
|
||||
return pl.netranges[n] >= ip
|
||||
})
|
||||
return index
|
||||
}
|
||||
|
||||
func (pl *sIPPool) Get(ip netutils.IPV4Addr) (sSimpleNet, bool) {
|
||||
index := pl.getIndex(ip)
|
||||
if index > len(pl.netranges) || index < 0 {
|
||||
return sSimpleNet{}, false
|
||||
}
|
||||
if index < len(pl.netranges) && pl.netranges[index] == ip {
|
||||
return pl.simpleNetMap[ip], true
|
||||
}
|
||||
if index == 0 {
|
||||
return sSimpleNet{}, false
|
||||
}
|
||||
startIp := pl.netranges[index-1]
|
||||
simpleNet := pl.simpleNetMap[startIp]
|
||||
if ip-startIp <= simpleNet.Diff {
|
||||
return simpleNet, true
|
||||
}
|
||||
return sSimpleNet{}, false
|
||||
}
|
||||
|
||||
// The suggestVMNetworks give the suggest config of network that contain the IP in 'ips' and does not intersect with the network segment described in 'excludes'.
|
||||
// The suggested network mask is 24 and the gateway is x.x.x.1.
|
||||
// The suggests network is the largest network segment that meets the above conditions.
|
||||
@@ -2565,7 +2640,7 @@ func (account *SCloudaccount) SubmitSyncAccountTask(ctx context.Context, userCre
|
||||
cloudaccountPendingSyncs[account.Id] = struct{}{}
|
||||
|
||||
RunSyncCloudAccountTask(ctx, func() {
|
||||
func() {
|
||||
defer func() {
|
||||
cloudaccountPendingSyncsMutex.Lock()
|
||||
defer cloudaccountPendingSyncsMutex.Unlock()
|
||||
delete(cloudaccountPendingSyncs, account.Id)
|
||||
@@ -3287,7 +3362,7 @@ func (self *SCloudaccount) SyncAccountResources(ctx context.Context, userCred mc
|
||||
return errors.Wrapf(err, "GetProvider")
|
||||
}
|
||||
if cloudprovider.IsSupportProject(provider) {
|
||||
return func() error {
|
||||
err = func() error {
|
||||
lockman.LockRawObject(ctx, "projects", self.Id)
|
||||
defer lockman.ReleaseRawObject(ctx, "projects", self.Id)
|
||||
|
||||
@@ -3299,10 +3374,13 @@ func (self *SCloudaccount) SyncAccountResources(ctx context.Context, userCred mc
|
||||
log.Infof("Sync project for cloudaccount %s result: %s", self.Name, result.Result())
|
||||
return nil
|
||||
}()
|
||||
if err != nil {
|
||||
log.Errorf("sync project for account %s error: %v", self.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
if cloudprovider.IsSupportDnsZone(provider) {
|
||||
return func() error {
|
||||
err = func() error {
|
||||
lockman.LockRawObject(ctx, "dns_zones", self.Id)
|
||||
defer lockman.ReleaseRawObject(ctx, "dns_zones", self.Id)
|
||||
|
||||
@@ -3327,6 +3405,9 @@ func (self *SCloudaccount) SyncAccountResources(ctx context.Context, userCred mc
|
||||
}
|
||||
return nil
|
||||
}()
|
||||
if err != nil {
|
||||
log.Errorf("sync dns zone for account %s error: %v", self.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -38,6 +38,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/policy"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
@@ -537,6 +538,7 @@ func (manager *SDBInstanceManager) FetchCustomizeColumns(
|
||||
manRows := manager.SManagedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
regRows := manager.SCloudregionResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
|
||||
rdsIds := make([]string, len(rows))
|
||||
vpcIds := make([]string, len(rows))
|
||||
zone1Ids := make([]string, len(rows))
|
||||
zone2Ids := make([]string, len(rows))
|
||||
@@ -548,6 +550,7 @@ func (manager *SDBInstanceManager) FetchCustomizeColumns(
|
||||
CloudregionResourceInfo: regRows[i],
|
||||
}
|
||||
instance := objs[i].(*SDBInstance)
|
||||
rdsIds[i] = instance.Id
|
||||
vpcIds[i] = instance.VpcId
|
||||
zone1Ids[i] = instance.Zone1
|
||||
zone2Ids[i] = instance.Zone2
|
||||
@@ -569,6 +572,42 @@ func (manager *SDBInstanceManager) FetchCustomizeColumns(
|
||||
}
|
||||
}
|
||||
|
||||
q := SecurityGroupManager.Query()
|
||||
ownerId, queryScope, err := db.FetchCheckQueryOwnerScope(ctx, userCred, query, SecurityGroupManager, policy.PolicyActionList, true)
|
||||
if err != nil {
|
||||
log.Errorf("FetchCheckQueryOwnerScope error: %v", err)
|
||||
return rows
|
||||
}
|
||||
secgroups := SecurityGroupManager.FilterByOwner(q, ownerId, queryScope).SubQuery()
|
||||
rdssecgroups := DBInstanceSecgroupManager.Query().SubQuery()
|
||||
|
||||
secQ := rdssecgroups.Query(rdssecgroups.Field("dbinstance_id"), rdssecgroups.Field("secgroup_id"), secgroups.Field("name").Label("secgroup_name")).Join(secgroups, sqlchemy.Equals(rdssecgroups.Field("secgroup_id"), secgroups.Field("id"))).Filter(sqlchemy.In(rdssecgroups.Field("dbinstance_id"), rdsIds))
|
||||
|
||||
type sRdsSecgroupInfo struct {
|
||||
DBInstanceId string `json:"dbinstance_id"`
|
||||
SecgroupName string
|
||||
SecgroupId string
|
||||
}
|
||||
rsgs := []sRdsSecgroupInfo{}
|
||||
err = secQ.All(&rsgs)
|
||||
if err != nil {
|
||||
log.Errorf("secQ.All error: %v", err)
|
||||
return rows
|
||||
}
|
||||
|
||||
ret := make(map[string][]apis.StandaloneShortDesc)
|
||||
for i := range rsgs {
|
||||
rsg, ok := ret[rsgs[i].DBInstanceId]
|
||||
if !ok {
|
||||
rsg = make([]apis.StandaloneShortDesc, 0)
|
||||
}
|
||||
rsg = append(rsg, apis.StandaloneShortDesc{
|
||||
Id: rsgs[i].SecgroupId,
|
||||
Name: rsgs[i].SecgroupName,
|
||||
})
|
||||
ret[rsgs[i].DBInstanceId] = rsg
|
||||
}
|
||||
|
||||
zone1, err := db.FetchIdNameMap2(ZoneManager, zone1Ids)
|
||||
if err != nil {
|
||||
return rows
|
||||
@@ -588,6 +627,7 @@ func (manager *SDBInstanceManager) FetchCustomizeColumns(
|
||||
rows[i].Zone1Name = zone1[zone1Ids[i]]
|
||||
rows[i].Zone2Name = zone2[zone2Ids[i]]
|
||||
rows[i].Zone3Name = zone3[zone3Ids[i]]
|
||||
rows[i].Secgroups, _ = ret[rdsIds[i]]
|
||||
}
|
||||
|
||||
return rows
|
||||
|
||||
@@ -432,18 +432,21 @@ func (self *SGuest) PerformLiveMigrate(ctx context.Context, userCred mcclient.To
|
||||
host := iHost.(*SHost)
|
||||
preferHostId = host.Id
|
||||
}
|
||||
err := self.StartGuestLiveMigrateTask(ctx, userCred, self.Status, preferHostId, "")
|
||||
err := self.StartGuestLiveMigrateTask(ctx, userCred, self.Status, preferHostId, input.SkipCpuCheck, "")
|
||||
return nil, err
|
||||
}
|
||||
return nil, httperrors.NewBadRequestError("Cannot live migrate in status %s", self.Status)
|
||||
}
|
||||
|
||||
func (self *SGuest) StartGuestLiveMigrateTask(ctx context.Context, userCred mcclient.TokenCredential, guestStatus, preferHostId, parentTaskId string) error {
|
||||
func (self *SGuest) StartGuestLiveMigrateTask(ctx context.Context, userCred mcclient.TokenCredential, guestStatus, preferHostId string, skipCpuCheck *bool, parentTaskId string) error {
|
||||
self.SetStatus(userCred, api.VM_START_MIGRATE, "")
|
||||
data := jsonutils.NewDict()
|
||||
if len(preferHostId) > 0 {
|
||||
data.Set("prefer_host_id", jsonutils.NewString(preferHostId))
|
||||
}
|
||||
if skipCpuCheck != nil {
|
||||
data.Set("skip_cpu_check", jsonutils.NewBool(*skipCpuCheck))
|
||||
}
|
||||
data.Set("guest_status", jsonutils.NewString(guestStatus))
|
||||
dedicateMigrateTask := "GuestLiveMigrateTask"
|
||||
if self.GetHypervisor() != api.HYPERVISOR_KVM {
|
||||
@@ -805,6 +808,16 @@ func (self *SGuest) AllowPerformStart(ctx context.Context,
|
||||
func (self *SGuest) PerformStart(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject,
|
||||
data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
if utils.IsInStringArray(self.Status, []string{api.VM_READY, api.VM_START_FAILED, api.VM_SAVE_DISK_FAILED, api.VM_SUSPEND}) {
|
||||
if !self.guestDisksStorageTypeIsShared() {
|
||||
host := self.GetHost()
|
||||
guestsMem, err := host.GetNotReadyGuestsMemorySize()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if float32(guestsMem+self.VmemSize) > host.GetVirtualMemorySize() {
|
||||
return nil, httperrors.NewInsufficientResourceError("host virtual memory not enough")
|
||||
}
|
||||
}
|
||||
if self.isAllDisksReady() {
|
||||
var kwargs *jsonutils.JSONDict
|
||||
if data != nil {
|
||||
@@ -2726,7 +2739,7 @@ func (self *SGuest) PerformStatus(ctx context.Context, userCred mcclient.TokenCr
|
||||
}
|
||||
|
||||
status := input.Status
|
||||
if len(self.BackupHostId) > 0 && status == api.VM_RUNNING {
|
||||
if len(self.BackupHostId) > 0 && status == api.VM_RUNNING && input.BlockJobsCount > 0 {
|
||||
self.SetMetadata(ctx, api.MIRROR_JOB, api.MIRROR_JOB_READY, userCred)
|
||||
} else if ispId := self.GetMetadata(api.BASE_INSTANCE_SNAPSHOT_ID, userCred); len(ispId) > 0 {
|
||||
ispM, err := InstanceSnapshotManager.FetchById(ispId)
|
||||
@@ -2763,6 +2776,27 @@ func (self *SGuest) PerformStop(ctx context.Context, userCred mcclient.TokenCred
|
||||
return nil, httperrors.NewInvalidStatusError("Cannot stop server in status %s", self.Status)
|
||||
}
|
||||
|
||||
func (self *SGuest) PerformFreeze(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformFreezeInput) (jsonutils.JSONObject, error) {
|
||||
if self.Freezed {
|
||||
return nil, httperrors.NewBadRequestError("virtual resource already freezed")
|
||||
}
|
||||
if utils.IsInStringArray(self.Status, []string{api.VM_RUNNING, api.VM_STOP_FAILED}) {
|
||||
return nil, self.StartGuestStopAndFreezeTask(ctx, userCred)
|
||||
} else {
|
||||
return self.SVirtualResourceBase.PerformFreeze(ctx, userCred, query, input)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SGuest) StartGuestStopAndFreezeTask(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
self.SetStatus(userCred, api.VM_START_STOP, "")
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "GuestStopAndFreezeTask", self, userCred, nil, "", "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) AllowPerformRestart(ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
|
||||
@@ -32,7 +32,6 @@ import (
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
"yunion.io/x/pkg/util/osprofile"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
"yunion.io/x/pkg/util/timeutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
@@ -365,11 +364,9 @@ func (manager *SGuestManager) ListItemFilter(
|
||||
if len(query.IpAddr) > 0 {
|
||||
gn := GuestnetworkManager.Query("guest_id").Contains("ip_addr", query.IpAddr).SubQuery()
|
||||
guestEip := ElasticipManager.Query("associate_id").Equals("associate_type", api.EIP_ASSOCIATE_TYPE_SERVER).Contains("ip_addr", query.IpAddr).SubQuery()
|
||||
q = q.LeftJoin(gn, sqlchemy.Equals(q.Field("id"), gn.Field("guest_id")))
|
||||
q = q.LeftJoin(guestEip, sqlchemy.Equals(q.Field("id"), guestEip.Field("associate_id")))
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
sqlchemy.IsNotNull(gn.Field("guest_id")),
|
||||
sqlchemy.IsNotNull(guestEip.Field("associate_id")),
|
||||
sqlchemy.In(q.Field("id"), gn),
|
||||
sqlchemy.In(q.Field("id"), guestEip),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -1324,6 +1321,13 @@ func (manager *SGuestManager) validateCreateData(
|
||||
}
|
||||
log.Debugf("ROOT DISK: %#v", rootDiskConfig)
|
||||
input.Disks[0] = rootDiskConfig
|
||||
if sku != nil {
|
||||
if len(rootDiskConfig.OsArch) >= 0 && len(sku.CpuArch) >= 0 {
|
||||
if strings.Contains(rootDiskConfig.OsArch, sku.CpuArch) {
|
||||
return nil, httperrors.NewConflictError("root disk image(%s) and sku(%s) architecture mismatch", rootDiskConfig.OsArch, sku.CpuArch)
|
||||
}
|
||||
}
|
||||
}
|
||||
//data.Set("disk.0", jsonutils.Marshal(rootDiskConfig))
|
||||
|
||||
for i := 0; i < len(dataDiskDefs); i += 1 {
|
||||
@@ -2334,31 +2338,6 @@ func (self *SGuest) getAdminSecgroupName() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SGuest) GetSecRules() []secrules.SecurityRule {
|
||||
return self.getSecRules()
|
||||
}
|
||||
|
||||
func (self *SGuest) getSecRules() []secrules.SecurityRule {
|
||||
if secgrp := self.getSecgroup(); secgrp != nil {
|
||||
return secgrp.GetSecRules("")
|
||||
}
|
||||
if rule, err := secrules.ParseSecurityRule(options.Options.DefaultSecurityRules); err == nil {
|
||||
return []secrules.SecurityRule{*rule}
|
||||
} else {
|
||||
log.Errorf("Default SecurityRules error: %v", err)
|
||||
}
|
||||
return []secrules.SecurityRule{}
|
||||
}
|
||||
|
||||
func (self *SGuest) getSecurityRules() string {
|
||||
secgrp := self.getSecgroup()
|
||||
if secgrp != nil {
|
||||
return secgrp.getSecurityRuleString("")
|
||||
} else {
|
||||
return options.Options.DefaultSecurityRules
|
||||
}
|
||||
}
|
||||
|
||||
//获取多个安全组规则,优先级降序排序
|
||||
func (self *SGuest) getSecurityGroupsRules() string {
|
||||
secgroups, _ := self.GetSecgroups()
|
||||
@@ -2383,7 +2362,8 @@ func (self *SGuest) getSecurityGroupsRules() string {
|
||||
func (self *SGuest) getAdminSecurityRules() string {
|
||||
secgrp := self.getAdminSecgroup()
|
||||
if secgrp != nil {
|
||||
return secgrp.getSecurityRuleString("")
|
||||
ret, _ := secgrp.getSecurityRuleString()
|
||||
return ret
|
||||
} else {
|
||||
return options.Options.DefaultAdminSecurityRules
|
||||
}
|
||||
@@ -4784,7 +4764,7 @@ func (self *SGuestManager) switchBackupGuests(ctx context.Context, userCred mccl
|
||||
log.Errorf("ReconcileBackupGuests failed fetch guests %s", err)
|
||||
return
|
||||
}
|
||||
log.Infof("Guests count %d need reconcile with switch bakcup", len(guests))
|
||||
log.Debugf("Guests count %d need reconcile with switch backup", len(guests))
|
||||
for i := 0; i < len(guests); i++ {
|
||||
val := guests[i].GetMetadataJson("switch_backup", userCred)
|
||||
t, err := val.GetTime()
|
||||
@@ -5276,8 +5256,11 @@ func (self *SGuest) ToCreateInput(userCred mcclient.TokenCredential) *api.Server
|
||||
userInput.KeypairId = genInput.KeypairId
|
||||
userInput.EipBw = genInput.EipBw
|
||||
userInput.EipChargeType = genInput.EipChargeType
|
||||
userInput.PublicIpBw = genInput.PublicIpBw
|
||||
userInput.PublicIpChargeType = genInput.PublicIpChargeType
|
||||
provider := self.GetDriver()
|
||||
if provider.IsSupportPublicIp() {
|
||||
userInput.PublicIpBw = genInput.PublicIpBw
|
||||
userInput.PublicIpChargeType = genInput.PublicIpChargeType
|
||||
}
|
||||
userInput.AutoRenew = genInput.AutoRenew
|
||||
// cloned server should belongs to the project creating it
|
||||
userInput.ProjectId = userCred.GetProjectId()
|
||||
@@ -5347,8 +5330,10 @@ func (self *SGuest) toCreateInput() *api.ServerCreateInput {
|
||||
r.EipBw = eip.Bandwidth
|
||||
r.EipChargeType = eip.ChargeType
|
||||
case api.EIP_MODE_INSTANCE_PUBLICIP:
|
||||
r.PublicIpBw = eip.Bandwidth
|
||||
r.PublicIpChargeType = eip.ChargeType
|
||||
if driver := self.GetDriver(); driver.IsSupportPublicIp() {
|
||||
r.PublicIpBw = eip.Bandwidth
|
||||
r.PublicIpChargeType = eip.ChargeType
|
||||
}
|
||||
}
|
||||
}
|
||||
if zone := self.getZone(); zone != nil {
|
||||
|
||||
@@ -251,6 +251,14 @@ func (manager *SHostManager) ListItemFilter(
|
||||
q = q.Equals("access_mac", anyMac)
|
||||
}
|
||||
}
|
||||
if len(query.AnyIp) > 0 {
|
||||
hn := HostnetworkManager.Query("baremetal_id").Contains("ip_addr", query.AnyIp).SubQuery()
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
sqlchemy.Contains(q.Field("access_ip"), query.AnyIp),
|
||||
sqlchemy.Contains(q.Field("ipmi_ip"), query.AnyIp),
|
||||
sqlchemy.In(q.Field("id"), hn),
|
||||
))
|
||||
}
|
||||
// var scopeQuery *sqlchemy.SSubQuery
|
||||
|
||||
schedTagStr := query.SchedtagId
|
||||
@@ -1497,6 +1505,23 @@ func (self *SHost) GetRunningGuestCount() (int, error) {
|
||||
return q.CountWithError()
|
||||
}
|
||||
|
||||
func (self *SHost) GetNotReadyGuestsMemorySize() (int, error) {
|
||||
guests := GuestManager.Query().SubQuery()
|
||||
q := guests.Query(sqlchemy.COUNT("guest_count"),
|
||||
sqlchemy.SUM("guest_vcpu_count", guests.Field("vcpu_count")),
|
||||
sqlchemy.SUM("guest_vmem_size", guests.Field("vmem_size")))
|
||||
cond := sqlchemy.OR(sqlchemy.Equals(q.Field("host_id"), self.Id),
|
||||
sqlchemy.Equals(q.Field("backup_host_id"), self.Id))
|
||||
q = q.Filter(cond)
|
||||
q = q.NotEquals("status", api.VM_READY)
|
||||
stat := SHostGuestResourceUsage{}
|
||||
err := q.First(&stat)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
return stat.GuestVmemSize, nil
|
||||
}
|
||||
|
||||
func (self *SHost) GetRunningGuestMemorySize() int {
|
||||
res := self.getGuestsResource(api.VM_RUNNING)
|
||||
if res != nil {
|
||||
|
||||
@@ -184,9 +184,9 @@ func (man *SAwsCachedLbbgManager) GetCachedBackendGroups(backendGroupId string)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (man *SAwsCachedLbbgManager) getLoadbalancerBackendgroupsByRegion(regionId string) ([]SAwsCachedLbbg, error) {
|
||||
func (man *SAwsCachedLbbgManager) getLoadbalancerBackendgroupsByRegion(managerId string, regionId string) ([]SAwsCachedLbbg, error) {
|
||||
lbbgs := []SAwsCachedLbbg{}
|
||||
q := man.Query().Equals("cloudregion_id", regionId).IsFalse("pending_deleted")
|
||||
q := man.Query().Equals("cloudregion_id", regionId).Equals("manager_id", managerId).IsFalse("pending_deleted")
|
||||
if err := db.FetchModelObjects(man, q, &lbbgs); err != nil {
|
||||
log.Errorf("failed to get lbbgs for region: %s error: %v", regionId, err)
|
||||
return nil, err
|
||||
@@ -204,7 +204,7 @@ func (man *SAwsCachedLbbgManager) SyncLoadbalancerBackendgroups(ctx context.Cont
|
||||
remoteLbbgs := []cloudprovider.ICloudLoadbalancerBackendGroup{}
|
||||
syncResult := compare.SyncResult{}
|
||||
|
||||
dbLbbgs, err := man.getLoadbalancerBackendgroupsByRegion(region.GetId())
|
||||
dbLbbgs, err := man.getLoadbalancerBackendgroupsByRegion(provider.GetId(), region.GetId())
|
||||
if err != nil {
|
||||
syncResult.Error(err)
|
||||
return nil, nil, syncResult
|
||||
|
||||
@@ -303,11 +303,11 @@ func (man *SLoadbalancerManager) ValidateCreateData(
|
||||
|
||||
var region *SCloudregion
|
||||
if len(input.VpcId) > 0 {
|
||||
var vpc *SVpc
|
||||
vpc, input.VpcResourceInput, err = ValidateVpcResourceInput(userCred, input.VpcResourceInput)
|
||||
_vpc, err := validators.ValidateModel(userCred, VpcManager, &input.VpcId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "ValidateVpcResourceInput")
|
||||
return nil, err
|
||||
}
|
||||
vpc := _vpc.(*SVpc)
|
||||
region, _ = vpc.GetRegion()
|
||||
} else if len(input.ZoneId) > 0 {
|
||||
var zone *SZone
|
||||
@@ -716,6 +716,19 @@ func (lb *SLoadbalancer) getMoreDetails(out api.LoadbalancerDetails) (api.Loadba
|
||||
}
|
||||
|
||||
func (lb *SLoadbalancer) ValidateDeleteCondition(ctx context.Context) error {
|
||||
err := lb.validatePurgeCondition(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if lb.DisableDelete.IsTrue() {
|
||||
return httperrors.NewInvalidStatusError("loadbalancer is locked, cannot delete")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lb *SLoadbalancer) validatePurgeCondition(ctx context.Context) error {
|
||||
region := lb.GetRegion()
|
||||
if region != nil {
|
||||
if err := region.GetDriver().ValidateDeleteLoadbalancerCondition(ctx, lb); err != nil {
|
||||
@@ -723,10 +736,6 @@ func (lb *SLoadbalancer) ValidateDeleteCondition(ctx context.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
if lb.DisableDelete.IsTrue() {
|
||||
return httperrors.NewInvalidStatusError("loadbalancer is locked, cannot delete")
|
||||
}
|
||||
|
||||
return lb.SModelBase.ValidateDeleteCondition(ctx)
|
||||
}
|
||||
|
||||
@@ -790,11 +799,9 @@ func (lb *SLoadbalancer) Delete(ctx context.Context, userCred mcclient.TokenCred
|
||||
|
||||
func (man *SLoadbalancerManager) getLoadbalancersByRegion(region *SCloudregion, provider *SCloudprovider) ([]SLoadbalancer, error) {
|
||||
lbs := []SLoadbalancer{}
|
||||
vpcs := VpcManager.Query().SubQuery()
|
||||
q := man.Query()
|
||||
q = q.Join(vpcs, sqlchemy.Equals(q.Field("vpc_id"), vpcs.Field("id")))
|
||||
q = q.Filter(sqlchemy.Equals(vpcs.Field("cloudregion_id"), region.Id))
|
||||
q = q.Filter(sqlchemy.Equals(vpcs.Field("manager_id"), provider.Id))
|
||||
q = q.Equals("manager_id", provider.Id)
|
||||
q = q.Equals("cloudregion_id", region.Id)
|
||||
q = q.IsFalse("pending_deleted")
|
||||
if err := db.FetchModelObjects(man, q, &lbs); err != nil {
|
||||
log.Errorf("failed to get lbs for region: %v provider: %v error: %v", region, provider, err)
|
||||
@@ -816,6 +823,12 @@ func (man *SLoadbalancerManager) getLoadbalancersByExternalIds(externalIds []str
|
||||
}
|
||||
|
||||
func (man *SLoadbalancerManager) getLocalLoadbalancers(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, region *SCloudregion, lbs []cloudprovider.ICloudLoadbalancer) ([]SLoadbalancer, error) {
|
||||
// current external ID
|
||||
extIds := []string{}
|
||||
for i := range lbs {
|
||||
extIds = append(extIds, lbs[i].GetGlobalId())
|
||||
}
|
||||
|
||||
part1, err := man.getLoadbalancersByRegion(region, provider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -824,15 +837,13 @@ func (man *SLoadbalancerManager) getLocalLoadbalancers(ctx context.Context, user
|
||||
localLbs := map[string]SLoadbalancer{}
|
||||
for i := range part1 {
|
||||
localLbs[part1[i].Id] = part1[i]
|
||||
if len(part1[i].GetExternalId()) > 0 {
|
||||
extIds = append(extIds, part1[i].GetExternalId())
|
||||
}
|
||||
}
|
||||
|
||||
externalIds := []string{}
|
||||
for i := range lbs {
|
||||
externalIds = append(externalIds, lbs[i].GetGlobalId())
|
||||
}
|
||||
|
||||
if len(externalIds) > 0 {
|
||||
part2, err := man.getLoadbalancersByExternalIds(externalIds)
|
||||
if len(extIds) > 0 {
|
||||
part2, err := man.getLoadbalancersByExternalIds(extIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -842,7 +853,7 @@ func (man *SLoadbalancerManager) getLocalLoadbalancers(ctx context.Context, user
|
||||
}
|
||||
}
|
||||
|
||||
ret := []SLoadbalancer{}
|
||||
ret := make([]SLoadbalancer, 0)
|
||||
for id, _ := range localLbs {
|
||||
ret = append(ret, localLbs[id])
|
||||
}
|
||||
@@ -860,7 +871,7 @@ func (man *SLoadbalancerManager) SyncLoadbalancers(ctx context.Context, userCred
|
||||
remoteLbs := []cloudprovider.ICloudLoadbalancer{}
|
||||
syncResult := compare.SyncResult{}
|
||||
|
||||
dbLbs, err := man.getLocalLoadbalancers(ctx, userCred, provider, region, remoteLbs)
|
||||
dbLbs, err := man.getLocalLoadbalancers(ctx, userCred, provider, region, lbs)
|
||||
if err != nil {
|
||||
syncResult.Error(err)
|
||||
return nil, nil, syncResult
|
||||
@@ -1007,7 +1018,7 @@ func (lb *SLoadbalancer) syncRemoveCloudLoadbalancer(ctx context.Context, userCr
|
||||
lockman.LockObject(ctx, lb)
|
||||
defer lockman.ReleaseObject(ctx, lb)
|
||||
|
||||
err := lb.ValidateDeleteCondition(ctx)
|
||||
err := lb.validatePurgeCondition(ctx)
|
||||
if err != nil { // cannot delete
|
||||
return lb.SetStatus(userCred, api.LB_STATUS_UNKNOWN, "sync to delete")
|
||||
} else {
|
||||
|
||||
@@ -298,6 +298,16 @@ func (self *SNetwork) ValidateElbNetwork(ipAddr net.IP) (*SCloudregion, *SZone,
|
||||
return region, zone, vpc, wire, nil
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetGuestnetworks() ([]SGuestnetwork, error) {
|
||||
q := GuestnetworkManager.Query().Equals("network_id", self.Id)
|
||||
gns := []SGuestnetwork{}
|
||||
err := db.FetchModelObjects(GuestnetworkManager, q, &gns)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return gns, nil
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetGuestnicsCount() (int, error) {
|
||||
return GuestnetworkManager.Query().Equals("network_id", self.Id).IsFalse("virtual").CountWithError()
|
||||
}
|
||||
@@ -1791,6 +1801,16 @@ func (self *SNetwork) RealDelete(ctx context.Context, userCred mcclient.TokenCre
|
||||
return errors.Wrapf(err, "reservedIps.Release %s(%d)", reservedIps[i].IpAddr, reservedIps[i].Id)
|
||||
}
|
||||
}
|
||||
gns, err := self.GetGuestnetworks() // delete virtual nics
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetGuestnetworks")
|
||||
}
|
||||
for i := range gns {
|
||||
err = gns[i].Delete(ctx, userCred)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "delete virtual nic %s(%d)", gns[i].Ifname, gns[i].RowId)
|
||||
}
|
||||
}
|
||||
if err := self.SSharableVirtualResourceBase.Delete(ctx, userCred); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -630,9 +630,9 @@ func (snapshot *SSnapshot) purge(ctx context.Context, userCred mcclient.TokenCre
|
||||
lockman.LockObject(ctx, snapshot)
|
||||
defer lockman.ReleaseObject(ctx, snapshot)
|
||||
|
||||
err := snapshot.ValidateDeleteCondition(ctx)
|
||||
err := snapshot.ValidatePurgeCondition(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrapf(err, "ValidatePurgeCondition for snapshot %s(%s)", snapshot.Name, snapshot.Id)
|
||||
}
|
||||
return snapshot.RealDelete(ctx, userCred)
|
||||
}
|
||||
|
||||
@@ -129,12 +129,13 @@ type IRegionDriver interface {
|
||||
|
||||
RequestCacheSecurityGroup(ctx context.Context, userCred mcclient.TokenCredential, region *SCloudregion, vpc *SVpc, secgroup *SSecurityGroup, classic bool, removeProjectId string, task taskman.ITask) error
|
||||
RequestSyncSecurityGroup(ctx context.Context, userCred mcclient.TokenCredential, vpcId string, vpc *SVpc, secgroup *SSecurityGroup, removeProjectId, service string) (string, error)
|
||||
GetSecurityGroupRuleOrder() cloudprovider.TPriorityOrder // Desc(priority值越大,优先级越高) Asc(priority值越小,优先级越高)
|
||||
GetDefaultSecurityGroupInRule() cloudprovider.SecurityRule
|
||||
GetDefaultSecurityGroupOutRule() cloudprovider.SecurityRule
|
||||
GetSecurityGroupRuleMaxPriority() int
|
||||
GetSecurityGroupRuleMinPriority() int
|
||||
IsOnlySupportAllowRules() bool
|
||||
IsPeerSecgroupWithSameProject() bool
|
||||
IsSupportPeerSecgroup() bool
|
||||
IsSupportClassicSecurityGroup() bool
|
||||
IsSecurityGroupBelongVpc() bool
|
||||
IsVpcBelongGlobalVpc() bool
|
||||
|
||||
@@ -155,9 +155,9 @@ func (man *SRouteTableManager) ValidateCreateData(
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "validateRoutes")
|
||||
}
|
||||
_, input.VpcResourceInput, err = ValidateVpcResourceInput(userCred, input.VpcResourceInput)
|
||||
_, err = validators.ValidateModel(userCred, VpcManager, &input.VpcId)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "ValidateVpcResourceInput")
|
||||
return input, err
|
||||
}
|
||||
input.StatusInfrasResourceBaseCreateInput, err = man.SStatusInfrasResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StatusInfrasResourceBaseCreateInput)
|
||||
if err != nil {
|
||||
|
||||
@@ -31,6 +31,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
@@ -136,7 +137,7 @@ func (sgm *SScalingGroupManager) ValidateCreateData(ctx context.Context, userCre
|
||||
input.CloudregionId = cloudregion.GetId()
|
||||
|
||||
// check vpc
|
||||
_, input.VpcResourceInput, err = ValidateVpcResourceInput(userCred, input.VpcResourceInput)
|
||||
_, err = validators.ValidateModel(userCred, VpcManager, &input.VpcId)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
|
||||
@@ -18,8 +18,6 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
@@ -205,17 +203,7 @@ func (st *SScalingTimer) TriggerId() string {
|
||||
var cstSh, _ = time.LoadLocation("Asia/Shanghai")
|
||||
|
||||
func (st *SScalingTimer) TriggerDescription() string {
|
||||
var detail string
|
||||
switch st.Type {
|
||||
case api.TIMER_TYPE_ONCE:
|
||||
detail = st.EndTime.In(cstSh).Format("2006-01-02 15:04:05")
|
||||
case api.TIMER_TYPE_DAY:
|
||||
detail = fmt.Sprintf("%d:%d every day", st.Hour, st.Minute)
|
||||
case api.TIMER_TYPE_WEEK:
|
||||
detail = st.WeekDaysDesc()
|
||||
case api.TIMER_TYPE_MONTH:
|
||||
detail = st.MonthDaysDesc()
|
||||
}
|
||||
detail := st.descEnglish()
|
||||
name := st.ScalingPolicyId
|
||||
sp, _ := st.ScalingPolicy()
|
||||
if sp != nil {
|
||||
@@ -336,11 +324,14 @@ var indicatorMap = map[string]sTableField{
|
||||
api.INDICATOR_FLOW_OUT: {"vm_netio", "bps_sent"},
|
||||
}
|
||||
|
||||
var alertConfigUsedBy = "scaling_group"
|
||||
|
||||
func (sa *SScalingAlarm) generateAlertConfig(sp *SScalingPolicy) (*monitor.AlertConfig, error) {
|
||||
config, err := monitor.NewAlertConfig(fmt.Sprintf("sp-%s", sp.Id), fmt.Sprintf("%ds", sa.Cycle), true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.UsedBy = alertConfigUsedBy
|
||||
cond := config.Condition("telegraf", indicatorMap[sa.Indicator].Table).Avg()
|
||||
log.Debugf("alarm: %#v", sa)
|
||||
|
||||
@@ -442,61 +433,3 @@ var units = map[string]string{
|
||||
api.INDICATOR_FLOW_INTO: "KB/s",
|
||||
api.INDICATOR_FLOW_OUT: "KB/s",
|
||||
}
|
||||
|
||||
var weekDays = []string{"", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}
|
||||
|
||||
func (st *SScalingTimer) WeekDaysDesc() string {
|
||||
if st.WeekDays == 0 {
|
||||
return ""
|
||||
}
|
||||
var desc strings.Builder
|
||||
wds := st.GetWeekDays()
|
||||
i := 0
|
||||
desc.WriteString(fmt.Sprintf("%d:%d every %s", st.Hour, st.Minute, weekDays[wds[i]]))
|
||||
for i++; i < len(wds)-1; i++ {
|
||||
desc.WriteString(", ")
|
||||
desc.WriteString(weekDays[wds[i]])
|
||||
}
|
||||
if i == len(wds)-1 {
|
||||
desc.WriteString(" and ")
|
||||
desc.WriteString(weekDays[wds[i]])
|
||||
}
|
||||
return desc.String()
|
||||
}
|
||||
|
||||
func (st *SScalingTimer) MonthDaysDesc() string {
|
||||
if st.MonthDays == 0 {
|
||||
return ""
|
||||
}
|
||||
var desc strings.Builder
|
||||
mds := st.GetMonthDays()
|
||||
i := 0
|
||||
desc.WriteString(fmt.Sprintf("%d:%d on the %d%s", st.Hour, st.Minute, mds[i], dateSuffix(mds[i])))
|
||||
for i++; i < len(mds)-1; i++ {
|
||||
desc.WriteString(", ")
|
||||
desc.WriteString(strconv.Itoa(mds[i]))
|
||||
desc.WriteString(dateSuffix(mds[i]))
|
||||
}
|
||||
if i == len(mds)-1 {
|
||||
desc.WriteString(" and ")
|
||||
desc.WriteString(strconv.Itoa(mds[i]))
|
||||
desc.WriteString(dateSuffix(mds[i]))
|
||||
}
|
||||
desc.WriteString(" of each month")
|
||||
return desc.String()
|
||||
}
|
||||
|
||||
func dateSuffix(date int) string {
|
||||
var ret string
|
||||
switch date {
|
||||
case 1:
|
||||
ret = "st"
|
||||
case 2:
|
||||
ret = "nd"
|
||||
case 3:
|
||||
ret = "rd"
|
||||
default:
|
||||
ret = "th"
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -72,7 +72,6 @@ type SScheduledTask struct {
|
||||
|
||||
STimer
|
||||
|
||||
TimerDesc string `width:"128" charset:"utf8" list:"user" get:"user"`
|
||||
ResourceType string `width:"32" charset:"ascii" create:"required" list:"user" get:"user"`
|
||||
Operation string `width:"32" charset:"ascii" create:"required" list:"user" get:"user"`
|
||||
LabelType string `width:"4" charset:"ascii" create:"required" list:"user" get:"user"`
|
||||
@@ -139,6 +138,7 @@ func (st *SScheduledTask) getMoreDetails(ctx context.Context, userCred mcclient.
|
||||
case api.ST_TYPE_CYCLE:
|
||||
out.CycleTimer = st.STimer.CycleTimerDetails()
|
||||
}
|
||||
out.TimerDesc = st.Description(ctx)
|
||||
// fill label
|
||||
stLabels, err := st.STLabels()
|
||||
if err != nil {
|
||||
@@ -184,36 +184,6 @@ func (stm *SScheduledTaskManager) ValidateCreateData(ctx context.Context, userCr
|
||||
return input, nil
|
||||
}
|
||||
|
||||
var wdsCN = []string{"", "一", "二", "三", "四", "五", "六", "日"}
|
||||
var zone = time.FixedZone("GMT", 8*3600)
|
||||
|
||||
func (st *SScheduledTask) TimerDescription() string {
|
||||
format := "2006-01-02 15:04:05"
|
||||
var prefix string
|
||||
timer := st.STimer
|
||||
switch timer.Type {
|
||||
case api.TIMER_TYPE_ONCE:
|
||||
return fmt.Sprintf("单次 %s触发", timer.StartTime.In(zone).Format(format))
|
||||
case api.TIMER_TYPE_DAY:
|
||||
prefix = "每天"
|
||||
case api.TIMER_TYPE_WEEK:
|
||||
wds := timer.GetWeekDays()
|
||||
weekDays := make([]string, len(wds))
|
||||
for i := range wds {
|
||||
weekDays[i] = fmt.Sprintf("星期%s", wdsCN[wds[i]])
|
||||
}
|
||||
prefix = fmt.Sprintf("每周 【%s】", strings.Join(weekDays, "|"))
|
||||
case api.TIMER_TYPE_MONTH:
|
||||
mns := timer.GetMonthDays()
|
||||
monthDays := make([]string, len(mns))
|
||||
for i := range mns {
|
||||
monthDays[i] = fmt.Sprintf("%d号", mns[i])
|
||||
}
|
||||
prefix = fmt.Sprintf("每月 【%s】", strings.Join(monthDays, "|"))
|
||||
}
|
||||
return fmt.Sprintf("%s %02d:%02d触发 有效时间为%s至%s", prefix, timer.Hour, timer.Minute, timer.StartTime.In(zone).Format(format), timer.EndTime.In(zone).Format(format))
|
||||
}
|
||||
|
||||
func (st *SScheduledTask) AllowPerformEnable(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, input apis.PerformEnableInput) bool {
|
||||
return true
|
||||
@@ -288,7 +258,7 @@ func (st *SScheduledTask) PostCreate(ctx context.Context, userCred mcclient.Toke
|
||||
st.Update(time.Time{})
|
||||
st.Status = api.ST_STATUS_READY
|
||||
st.Enabled = tristate.True
|
||||
st.TimerDesc = st.TimerDescription()
|
||||
// st.TimerDesc = st.Description(ctx)
|
||||
err = st.GetModelManager().TableSpec().InsertOrUpdate(ctx, st)
|
||||
if err != nil {
|
||||
createFailed("update itself")
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
@@ -33,6 +34,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/rand"
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
@@ -330,18 +332,22 @@ func (manager *SSecurityGroupCacheManager) NewCache(ctx context.Context, userCre
|
||||
return nil, errors.Wrapf(err, "SecurityGroupManager.FetchById(%s)", secgroupId)
|
||||
}
|
||||
|
||||
return manager.newCache(ctx, secgroupId, secgroup.GetName(), vpcId, regionId, providerId, projectId)
|
||||
}
|
||||
|
||||
func (manager *SSecurityGroupCacheManager) newCache(ctx context.Context, secgroupId, secgroupName, vpcId, regionId string, providerId string, projectId string) (*SSecurityGroupCache, error) {
|
||||
secgroupCache := &SSecurityGroupCache{}
|
||||
secgroupCache.SecgroupId = secgroupId
|
||||
secgroupCache.VpcId = vpcId
|
||||
secgroupCache.ManagerId = providerId
|
||||
secgroupCache.Status = api.SECGROUP_CACHE_STATUS_CACHING
|
||||
secgroupCache.CloudregionId = regionId
|
||||
secgroupCache.Name = secgroup.GetName()
|
||||
secgroupCache.Name = secgroupName
|
||||
secgroupCache.ExternalProjectId = projectId
|
||||
secgroupCache.SetModelManager(manager, secgroupCache)
|
||||
if err := manager.TableSpec().Insert(ctx, secgroupCache); err != nil {
|
||||
log.Errorf("insert secgroupcache error: %v", err)
|
||||
return nil, err
|
||||
err := manager.TableSpec().Insert(ctx, secgroupCache)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Insert")
|
||||
}
|
||||
return secgroupCache, nil
|
||||
}
|
||||
@@ -382,7 +388,7 @@ func (self *SSecurityGroupCache) GetSecgroup() (*SSecurityGroup, error) {
|
||||
return model.(*SSecurityGroup), nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroupCache) syncWithCloudSecurityGroup(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, ext cloudprovider.ICloudSecurityGroup) error {
|
||||
func (self *SSecurityGroupCache) syncWithCloudSecurityGroup(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, ext cloudprovider.ICloudSecurityGroup) ([]SSecurityGroupRule, error) {
|
||||
_, err := db.Update(self, func() error {
|
||||
self.Status = api.SECGROUP_CACHE_STATUS_READY
|
||||
self.Name = ext.GetName()
|
||||
@@ -391,28 +397,26 @@ func (self *SSecurityGroupCache) syncWithCloudSecurityGroup(ctx context.Context,
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "db.Update")
|
||||
return nil, errors.Wrapf(err, "db.Update")
|
||||
}
|
||||
secgroup, err := self.GetSecgroup()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetSecurity")
|
||||
return nil, errors.Wrapf(err, "GetSecurity")
|
||||
}
|
||||
cacheCount, err := secgroup.GetSecgroupCacheCount()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetSecgroupCacheCount")
|
||||
return nil, errors.Wrapf(err, "GetSecgroupCacheCount")
|
||||
}
|
||||
if cacheCount > 1 {
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
info, err := SecurityGroupManager.getRuleInfo(provider, ext)
|
||||
dest := cloudprovider.NewSecRuleInfo(GetRegionDriver(provider.Provider))
|
||||
dest.Rules, err = ext.GetRules()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "getRuleInfo")
|
||||
return nil, errors.Wrapf(err, "GetRules")
|
||||
}
|
||||
err = secgroup.SyncSecurityGroupRules(ctx, userCred, info)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "SyncSecurityGroupRules")
|
||||
}
|
||||
return nil
|
||||
rules, _ := secgroup.SyncSecurityGroupRules(ctx, userCred, dest)
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func (manager *SSecurityGroupCacheManager) SyncSecurityGroupCaches(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, secgroups []cloudprovider.ICloudSecurityGroup, vpc *SVpc) ([]SSecurityGroup, []cloudprovider.ICloudSecurityGroup, compare.SyncResult) {
|
||||
@@ -474,21 +478,25 @@ func (manager *SSecurityGroupCacheManager) SyncSecurityGroupCaches(ctx context.C
|
||||
}
|
||||
}
|
||||
|
||||
rules := []SSecurityGroupRule{}
|
||||
|
||||
for i := 0; i < len(commondb); i++ {
|
||||
err = commondb[i].syncWithCloudSecurityGroup(ctx, userCred, provider, commonext[i])
|
||||
_rules, err := commondb[i].syncWithCloudSecurityGroup(ctx, userCred, provider, commonext[i])
|
||||
if err != nil {
|
||||
syncResult.UpdateError(errors.Wrapf(err, "syncWithCloudSecurityGroup"))
|
||||
continue
|
||||
}
|
||||
rules = append(rules, _rules...)
|
||||
syncResult.Update()
|
||||
}
|
||||
|
||||
for i := 0; i < len(added); i++ {
|
||||
secgroup, err := SecurityGroupManager.newFromCloudSecgroup(ctx, userCred, provider, added[i])
|
||||
secgroup, _rules, err := SecurityGroupManager.newFromCloudSecgroup(ctx, userCred, provider, added[i])
|
||||
if err != nil {
|
||||
syncResult.AddError(errors.Wrapf(err, "newFromCloudSecgroup"))
|
||||
continue
|
||||
}
|
||||
rules = append(rules, _rules...)
|
||||
if secgroup.ProjectId != provider.ProjectId {
|
||||
_, err = secgroup.PerformPublic(ctx, userCred, nil,
|
||||
apis.PerformPublicProjectInput{
|
||||
@@ -521,6 +529,17 @@ func (manager *SSecurityGroupCacheManager) SyncSecurityGroupCaches(ctx context.C
|
||||
remoteSecgroups = append(remoteSecgroups, added[i])
|
||||
syncResult.Add()
|
||||
}
|
||||
for i := range rules {
|
||||
if len(rules[i].PeerSecgroupId) > 0 {
|
||||
cache, _ := db.FetchByExternalId(SecurityGroupCacheManager, rules[i].PeerSecgroupId)
|
||||
if cache != nil {
|
||||
db.Update(&rules[i], func() error {
|
||||
rules[i].PeerSecgroupId = cache.(*SSecurityGroupCache).SecgroupId
|
||||
return nil
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return localSecgroups, remoteSecgroups, syncResult
|
||||
}
|
||||
|
||||
@@ -616,7 +635,7 @@ func (manager *SSecurityGroupCacheManager) ListItemExportKeys(ctx context.Contex
|
||||
|
||||
func (self *SSecurityGroupCache) GetISecurityGroup() (cloudprovider.ICloudSecurityGroup, error) {
|
||||
if len(self.ExternalId) == 0 {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "empty externalId")
|
||||
return self.CreateISecurityGroup()
|
||||
}
|
||||
|
||||
manager := self.GetCloudprovider()
|
||||
@@ -628,5 +647,165 @@ func (self *SSecurityGroupCache) GetISecurityGroup() (cloudprovider.ICloudSecuri
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetIRegion")
|
||||
}
|
||||
return iRegion.GetISecurityGroupById(self.ExternalId)
|
||||
iSecgroup, err := iRegion.GetISecurityGroupById(self.ExternalId)
|
||||
if err != nil {
|
||||
if errors.Cause(err) != cloudprovider.ErrNotFound {
|
||||
return nil, errors.Wrap(err, "iRegion.GetSecurityGroupById")
|
||||
}
|
||||
return self.CreateISecurityGroup()
|
||||
}
|
||||
return iSecgroup, nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroupCache) CreateISecurityGroup() (cloudprovider.ICloudSecurityGroup, error) {
|
||||
iRegion, err := self.GetIRegion()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "self.GetIRegion")
|
||||
}
|
||||
|
||||
if strings.ToLower(self.Name) == "default" { //避免有些云不支持default关键字
|
||||
self.Name = "DefaultGroup"
|
||||
}
|
||||
// 避免有的云不支持重名安全组
|
||||
randomString := func(prefix string, length int) string {
|
||||
return fmt.Sprintf("%s-%s", prefix, rand.String(length))
|
||||
}
|
||||
opts := &cloudprovider.SecurityGroupFilterOptions{
|
||||
Name: randomString(self.Name, 1),
|
||||
VpcId: self.VpcId,
|
||||
ProjectId: self.ExternalProjectId,
|
||||
}
|
||||
for i := 2; i < 30; i++ {
|
||||
_, err := iRegion.GetISecurityGroupByName(opts)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == cloudprovider.ErrNotFound {
|
||||
break
|
||||
}
|
||||
if errors.Cause(err) != cloudprovider.ErrDuplicateId {
|
||||
return nil, errors.Wrapf(err, "GetISecurityGroupByName")
|
||||
}
|
||||
}
|
||||
opts.Name = randomString(self.Name, i)
|
||||
}
|
||||
conf := &cloudprovider.SecurityGroupCreateInput{
|
||||
Name: opts.Name,
|
||||
Desc: self.Description,
|
||||
VpcId: self.VpcId,
|
||||
ProjectId: self.ExternalProjectId,
|
||||
}
|
||||
iSecgroup, err := iRegion.CreateISecurityGroup(conf)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "iRegion.CreateISecurityGroup")
|
||||
}
|
||||
_, err = db.Update(self, func() error {
|
||||
self.ExternalId = iSecgroup.GetGlobalId()
|
||||
self.Name = iSecgroup.GetName()
|
||||
self.Status = api.SECGROUP_CACHE_STATUS_READY
|
||||
return nil
|
||||
})
|
||||
return iSecgroup, nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroupCache) GetSecuritRuleSet() (cloudprovider.SecurityRuleSet, []SSecurityGroupCache, error) {
|
||||
ruleSet := cloudprovider.SecurityRuleSet{}
|
||||
secgroup, err := self.GetSecgroup()
|
||||
if err != nil {
|
||||
return ruleSet, nil, errors.Wrapf(err, "GetSecgroup")
|
||||
}
|
||||
rules, err := secgroup.getSecurityRules()
|
||||
if err != nil {
|
||||
return ruleSet, nil, errors.Wrapf(err, "getSecurityRules")
|
||||
}
|
||||
|
||||
caches := []SSecurityGroupCache{}
|
||||
|
||||
driver := GetRegionDriver(self.GetProviderName())
|
||||
for i := range rules {
|
||||
if !driver.IsSupportPeerSecgroup() && len(rules[i].PeerSecgroupId) > 0 {
|
||||
continue
|
||||
}
|
||||
//这里没必要拆分为单个单个的端口,到公有云那边适配
|
||||
rule, err := rules[i].toRule()
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "toRule")
|
||||
}
|
||||
peerId := ""
|
||||
if len(rules[i].PeerSecgroupId) > 0 {
|
||||
_peerSecgroup, err := SecurityGroupManager.FetchById(rules[i].PeerSecgroupId)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "SecurityGroupManager.FetchById(%s)", rules[i].PeerSecgroupId)
|
||||
}
|
||||
peerSecgroup := _peerSecgroup.(*SSecurityGroup)
|
||||
peerCaches, err := peerSecgroup.GetSecurityGroupCaches()
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "peerSecgroup.GetSecurityGroupCaches")
|
||||
}
|
||||
|
||||
for _, cache := range peerCaches {
|
||||
if cache.ManagerId == self.ManagerId && cache.VpcId == self.VpcId && len(cache.ExternalId) > 0 && (!driver.IsPeerSecgroupWithSameProject() || cache.ExternalProjectId == self.ExternalProjectId) {
|
||||
peerId = cache.ExternalId
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(peerId) == 0 {
|
||||
cache, err := SecurityGroupCacheManager.newCache(context.TODO(), peerSecgroup.Id, peerSecgroup.Name, self.VpcId, self.CloudregionId, self.ManagerId, self.ExternalProjectId)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "SecurityGroupCacheManager.newCache")
|
||||
}
|
||||
iSecgroup, err := cache.CreateISecurityGroup()
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "cache.CreateISecurityGroup")
|
||||
}
|
||||
peerId = iSecgroup.GetGlobalId()
|
||||
caches = append(caches, *cache)
|
||||
}
|
||||
}
|
||||
ruleSet = append(ruleSet, cloudprovider.SecurityRule{SecurityRule: *rule, ExternalId: rules[i].Id, PeerSecgroupId: peerId})
|
||||
}
|
||||
return ruleSet, caches, nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroupCache) SyncRules() error {
|
||||
region := self.GetRegion()
|
||||
if region == nil {
|
||||
return fmt.Errorf("failed to get region for secgroupcache %s(%s)", self.Name, self.Id)
|
||||
}
|
||||
iSecgroup, err := self.GetISecurityGroup()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetISecurityGroup")
|
||||
}
|
||||
|
||||
rules, err := iSecgroup.GetRules()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "iSecgroup.GetRules")
|
||||
}
|
||||
|
||||
localRules, caches, err := self.GetSecuritRuleSet()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetSecuritRuleSet")
|
||||
}
|
||||
|
||||
src := cloudprovider.NewSecRuleInfo(GetRegionDriver(api.CLOUD_PROVIDER_ONECLOUD))
|
||||
src.Rules = localRules
|
||||
|
||||
dest := cloudprovider.NewSecRuleInfo(GetRegionDriver(region.Provider))
|
||||
dest.Rules = rules
|
||||
|
||||
common, inAdds, outAdds, inDels, outDels := cloudprovider.CompareRules(src, dest, false)
|
||||
|
||||
if len(inAdds) == 0 && len(inDels) == 0 && len(outAdds) == 0 && len(outDels) == 0 {
|
||||
return nil
|
||||
}
|
||||
err = iSecgroup.SyncRules(common, inAdds, outAdds, inDels, outDels)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "iSecgroup.SyncRules")
|
||||
}
|
||||
for i := range caches {
|
||||
err = caches[i].SyncRules()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "SyncRules for caches %s(%s)", caches[i].Name, caches[i].Id)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package models
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
@@ -27,7 +26,6 @@ import (
|
||||
"yunion.io/x/pkg/util/stringutils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
@@ -63,40 +61,21 @@ type SSecurityGroupRule struct {
|
||||
db.SResourceBase
|
||||
SSecurityGroupResourceBase `create:"required"`
|
||||
|
||||
Id string `width:"128" charset:"ascii" primary:"true" list:"user"`
|
||||
Priority int64 `default:"1" list:"user" update:"user" list:"user"`
|
||||
Protocol string `width:"5" charset:"ascii" nullable:"false" list:"user" update:"user" create:"required"`
|
||||
Ports string `width:"256" charset:"ascii" list:"user" update:"user" create:"optional"`
|
||||
Direction string `width:"3" charset:"ascii" list:"user" create:"required"`
|
||||
CIDR string `width:"256" charset:"ascii" list:"user" update:"user" create:"required"`
|
||||
Action string `width:"5" charset:"ascii" nullable:"false" list:"user" update:"user" create:"required"`
|
||||
Description string `width:"256" charset:"utf8" list:"user" update:"user" create:"optional"`
|
||||
// SecgroupID string `width:"128" charset:"ascii" create:"required"`
|
||||
Id string `width:"128" charset:"ascii" primary:"true" list:"user"`
|
||||
Priority int64 `default:"1" list:"user" update:"user" list:"user"`
|
||||
Protocol string `width:"5" charset:"ascii" nullable:"false" list:"user" update:"user" create:"required"`
|
||||
Ports string `width:"256" charset:"ascii" list:"user" update:"user" create:"optional"`
|
||||
Direction string `width:"3" charset:"ascii" list:"user" create:"required"`
|
||||
CIDR string `width:"256" charset:"ascii" list:"user" update:"user" create:"optional"`
|
||||
Action string `width:"5" charset:"ascii" nullable:"false" list:"user" update:"user" create:"required"`
|
||||
Description string `width:"256" charset:"utf8" list:"user" update:"user" create:"optional"`
|
||||
PeerSecgroupId string `width:"128" charset:"ascii" create:"optional" list:"user" update:"user"`
|
||||
}
|
||||
|
||||
func (self *SSecurityGroupRule) GetId() string {
|
||||
return self.Id
|
||||
}
|
||||
|
||||
type SecurityGroupRuleSet []SSecurityGroupRule
|
||||
|
||||
func (v SecurityGroupRuleSet) Len() int {
|
||||
return len(v)
|
||||
}
|
||||
|
||||
func (v SecurityGroupRuleSet) Swap(i, j int) {
|
||||
v[i], v[j] = v[j], v[i]
|
||||
}
|
||||
|
||||
func (v SecurityGroupRuleSet) Less(i, j int) bool {
|
||||
if v[i].Priority < v[j].Priority {
|
||||
return true
|
||||
} else if v[i].Priority == v[j].Priority {
|
||||
return strings.Compare(v[i].String(), v[j].String()) <= 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (manager *SSecurityGroupRuleManager) FetchUniqValues(ctx context.Context, data jsonutils.JSONObject) jsonutils.JSONObject {
|
||||
secgroupId, _ := data.GetString("secgroup_id")
|
||||
return jsonutils.Marshal(map[string]string{"secgroup_id": secgroupId})
|
||||
@@ -150,13 +129,6 @@ func (self *SSecurityGroupRule) AllowDeleteItem(ctx context.Context, userCred mc
|
||||
return false
|
||||
}
|
||||
|
||||
/*func (self *SSecurityGroupRule) GetSecGroup() *SSecurityGroup {
|
||||
if secgroup, _ := SecurityGroupManager.FetchById(self.SecgroupI); secgroup != nil {
|
||||
return secgroup.(*SSecurityGroup)
|
||||
}
|
||||
return nil
|
||||
}*/
|
||||
|
||||
func (manager *SSecurityGroupRuleManager) FilterById(q *sqlchemy.SQuery, idStr string) *sqlchemy.SQuery {
|
||||
return q.Equals("id", idStr)
|
||||
}
|
||||
@@ -226,6 +198,7 @@ func (manager *SSecurityGroupRuleManager) FetchCustomizeColumns(
|
||||
bRows := manager.SResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
secRows := manager.SSecurityGroupResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
secIds := make([]string, len(objs))
|
||||
peerIds := make([]string, len(objs))
|
||||
for i := range rows {
|
||||
rows[i] = api.SecgroupRuleDetails{
|
||||
ResourceBaseDetails: bRows[i],
|
||||
@@ -233,6 +206,7 @@ func (manager *SSecurityGroupRuleManager) FetchCustomizeColumns(
|
||||
}
|
||||
rule := objs[i].(*SSecurityGroupRule)
|
||||
secIds[i] = rule.SecgroupId
|
||||
peerIds[i] = rule.PeerSecgroupId
|
||||
}
|
||||
|
||||
secgroups := make(map[string]SSecurityGroup)
|
||||
@@ -242,6 +216,12 @@ func (manager *SSecurityGroupRuleManager) FetchCustomizeColumns(
|
||||
return rows
|
||||
}
|
||||
|
||||
peerMaps, err := db.FetchIdNameMap2(SecurityGroupManager, peerIds)
|
||||
if err != nil {
|
||||
log.Errorf("db.FetchIdNameMap2 fail: %v", err)
|
||||
return rows
|
||||
}
|
||||
|
||||
virObjs := make([]interface{}, len(objs))
|
||||
for i := range rows {
|
||||
if secgroup, ok := secgroups[secIds[i]]; ok {
|
||||
@@ -253,6 +233,7 @@ func (manager *SSecurityGroupRuleManager) FetchCustomizeColumns(
|
||||
projRows := SecurityGroupManager.SProjectizedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, virObjs, fields, isList)
|
||||
for i := range rows {
|
||||
rows[i].ProjectizedResourceInfo = projRows[i]
|
||||
rows[i].PeerSecgroup, _ = peerMaps[peerIds[i]]
|
||||
}
|
||||
|
||||
return rows
|
||||
@@ -304,30 +285,32 @@ func (self *SSecurityGroupRule) BeforeInsert() {
|
||||
}
|
||||
|
||||
func (manager *SSecurityGroupRuleManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.SSecgroupRuleCreateInput) (api.SSecgroupRuleCreateInput, error) {
|
||||
data := jsonutils.Marshal(input).(*jsonutils.JSONDict)
|
||||
if input.Priority == nil {
|
||||
return input, httperrors.NewMissingParameterError("priority")
|
||||
}
|
||||
if *input.Priority < 1 || *input.Priority > 100 {
|
||||
return input, httperrors.NewOutOfRangeError("Invalid priority %d, must be in range or 1 ~ 100", input.Priority)
|
||||
}
|
||||
|
||||
priorityV := validators.NewRangeValidator("priority", 1, 100)
|
||||
priorityV.Optional(true)
|
||||
err := priorityV.Validate(data)
|
||||
_secgroup, err := validators.ValidateModel(userCred, SecurityGroupManager, &input.SecgroupId)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
|
||||
secgroupV := validators.NewModelIdOrNameValidator("secgroup", "secgroup", ownerId)
|
||||
err = secgroupV.Validate(data)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
|
||||
secgroup := secgroupV.Model.(*SSecurityGroup)
|
||||
secgroup := _secgroup.(*SSecurityGroup)
|
||||
|
||||
if !secgroup.IsOwner(userCred) && !userCred.HasSystemAdminPrivilege() {
|
||||
return input, httperrors.NewForbiddenError("not enough privilege")
|
||||
}
|
||||
|
||||
err = data.Unmarshal(&input)
|
||||
if err != nil {
|
||||
return input, httperrors.NewInputParameterError("Failed to unmarshal input: %v", err)
|
||||
if len(input.PeerSecgroupId) > 0 {
|
||||
_, err = validators.ValidateModel(userCred, SecurityGroupManager, &input.PeerSecgroupId)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
if input.PeerSecgroupId == input.SecgroupId {
|
||||
return input, httperrors.NewInputParameterError("peer_secgroup_id can not point to secgroup self")
|
||||
}
|
||||
}
|
||||
|
||||
err = input.Check()
|
||||
@@ -342,48 +325,47 @@ func (manager *SSecurityGroupRuleManager) ValidateCreateData(ctx context.Context
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroupRule) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
priorityV := validators.NewRangeValidator("priority", 1, 100)
|
||||
priorityV.Optional(true)
|
||||
err := priorityV.Validate(data)
|
||||
func (self *SSecurityGroupRule) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.SSecgroupRuleUpdateInput) (api.SSecgroupRuleUpdateInput, error) {
|
||||
priority := int(self.Priority)
|
||||
output := api.SSecgroupRuleUpdateInput{
|
||||
SSecgroupRuleResource: api.SSecgroupRuleResource{
|
||||
Priority: &priority,
|
||||
Protocol: self.Protocol,
|
||||
Ports: self.Ports,
|
||||
Direction: self.Direction,
|
||||
CIDR: self.CIDR,
|
||||
Action: self.Action,
|
||||
Description: self.Description,
|
||||
PeerSecgroupId: self.PeerSecgroupId,
|
||||
},
|
||||
}
|
||||
jsonutils.Update(&output, input)
|
||||
|
||||
if *output.Priority < 1 || *output.Priority > 100 {
|
||||
return output, httperrors.NewOutOfRangeError("Invalid priority %d, must be in range or 1 ~ 100", input.Priority)
|
||||
}
|
||||
|
||||
if len(input.PeerSecgroupId) > 0 {
|
||||
_, err := validators.ValidateModel(userCred, SecurityGroupManager, &input.PeerSecgroupId)
|
||||
if err != nil {
|
||||
return output, err
|
||||
}
|
||||
if input.PeerSecgroupId == self.Id {
|
||||
return output, httperrors.NewInputParameterError("peer_secgroup_id can not point to secgroup self")
|
||||
}
|
||||
}
|
||||
|
||||
err := output.Check()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return output, err
|
||||
}
|
||||
|
||||
input := &api.SSecgroupRuleCreateInput{
|
||||
Direction: self.Direction,
|
||||
Action: self.Action,
|
||||
CIDR: self.CIDR,
|
||||
Protocol: self.Protocol,
|
||||
Ports: self.Ports,
|
||||
Priority: int(self.Priority),
|
||||
}
|
||||
|
||||
err = jsonutils.Update(input, data)
|
||||
output.ResourceBaseUpdateInput, err = self.SResourceBase.ValidateUpdateData(ctx, userCred, query, input.ResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return output, errors.Wrap(err, "SResourceBase.ValidateUpdateData")
|
||||
}
|
||||
|
||||
err = input.Check()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 更新操作日志: 对比可以知道改了原有规则哪些内容
|
||||
data.Add(jsonutils.Marshal(self), "origin")
|
||||
|
||||
rinput := apis.ResourceBaseUpdateInput{}
|
||||
err = data.Unmarshal(&rinput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Unmarshal")
|
||||
}
|
||||
rinput, err = self.SResourceBase.ValidateUpdateData(ctx, userCred, query, rinput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SResourceBase.ValidateUpdateData")
|
||||
}
|
||||
data.Update(jsonutils.Marshal(rinput))
|
||||
|
||||
return data, nil
|
||||
return output, nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroupRule) String() string {
|
||||
@@ -427,6 +409,13 @@ func (self *SSecurityGroupRule) toRule() (*secrules.SecurityRule, error) {
|
||||
func (self *SSecurityGroupRule) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
self.SResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
|
||||
|
||||
if len(self.PeerSecgroupId) > 0 {
|
||||
db.Update(self, func() error {
|
||||
self.CIDR = ""
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
log.Debugf("POST Create %s", data)
|
||||
if secgroup := self.GetSecGroup(); secgroup != nil {
|
||||
logclient.AddSimpleActionLog(secgroup, logclient.ACT_ALLOCATE, data, userCred, true)
|
||||
@@ -446,6 +435,13 @@ func (self *SSecurityGroupRule) PreDelete(ctx context.Context, userCred mcclient
|
||||
func (self *SSecurityGroupRule) PostUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
self.SResourceBase.PostUpdate(ctx, userCred, query, data)
|
||||
|
||||
if len(self.PeerSecgroupId) > 0 {
|
||||
db.Update(self, func() error {
|
||||
self.CIDR = ""
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
log.Debugf("POST Update %s", data)
|
||||
if secgroup := self.GetSecGroup(); secgroup != nil {
|
||||
logclient.AddSimpleActionLog(secgroup, logclient.ACT_UPDATE, data, userCred, true)
|
||||
@@ -462,27 +458,12 @@ func (manager *SSecurityGroupRuleManager) getRulesBySecurityGroup(secgroup *SSec
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) SyncRules(ctx context.Context, userCred mcclient.TokenCredential, rules cloudprovider.SecurityRuleSet) error {
|
||||
priority, prePriority := 10, 0
|
||||
for i := 0; i < len(rules); i++ {
|
||||
// 这里避免了Rule规则优先级在 1-100之外的问题,ext.GetRules()不需要进行优先级转换
|
||||
if prePriority != 0 && rules[i].Priority != prePriority && priority < 100 {
|
||||
priority++
|
||||
}
|
||||
prePriority = rules[i].Priority
|
||||
rules[i].Priority = priority
|
||||
_, err := self.newFromCloudSecurityGroupRule(ctx, userCred, rules[i])
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "newFromCloudSecurityGroupRule")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) newFromCloudSecurityGroupRule(ctx context.Context, userCred mcclient.TokenCredential, rule cloudprovider.SecurityRule) (*SSecurityGroupRule, error) {
|
||||
func (self *SSecurityGroup) newFromCloudSecurityGroupRule(ctx context.Context, userCred mcclient.TokenCredential, rule cloudprovider.SecurityRule) (*SSecurityGroupRule, bool, error) {
|
||||
lockman.LockObject(ctx, self)
|
||||
defer lockman.ReleaseObject(ctx, self)
|
||||
|
||||
isNeedFix := false
|
||||
|
||||
protocol := rule.Protocol
|
||||
if len(protocol) == 0 {
|
||||
protocol = secrules.PROTO_ANY
|
||||
@@ -493,23 +474,38 @@ func (self *SSecurityGroup) newFromCloudSecurityGroupRule(ctx context.Context, u
|
||||
cidr = rule.IPNet.String()
|
||||
}
|
||||
|
||||
if len(rule.PeerSecgroupId) > 0 {
|
||||
cidr = ""
|
||||
cache, _ := db.FetchByExternalId(SecurityGroupCacheManager, rule.PeerSecgroupId)
|
||||
if cache != nil {
|
||||
rule.PeerSecgroupId = cache.(*SSecurityGroupCache).SecgroupId
|
||||
}
|
||||
isNeedFix = true
|
||||
}
|
||||
|
||||
err := rule.ValidateRule()
|
||||
if err != nil {
|
||||
return nil, isNeedFix, errors.Wrapf(err, "ValidateRule %s ", jsonutils.Marshal(rule).String())
|
||||
}
|
||||
|
||||
secrule := &SSecurityGroupRule{
|
||||
Priority: int64(rule.Priority),
|
||||
Protocol: protocol,
|
||||
Ports: rule.GetPortsString(),
|
||||
Direction: string(rule.Direction),
|
||||
CIDR: cidr,
|
||||
Action: string(rule.Action),
|
||||
Description: rule.Description,
|
||||
Priority: int64(rule.Priority),
|
||||
Protocol: protocol,
|
||||
Ports: rule.GetPortsString(),
|
||||
Direction: string(rule.Direction),
|
||||
CIDR: cidr,
|
||||
Action: string(rule.Action),
|
||||
Description: rule.Description,
|
||||
PeerSecgroupId: rule.PeerSecgroupId,
|
||||
}
|
||||
secrule.SetModelManager(SecurityGroupRuleManager, secrule)
|
||||
secrule.SecgroupId = self.Id
|
||||
|
||||
err := SecurityGroupRuleManager.TableSpec().Insert(ctx, secrule)
|
||||
err = SecurityGroupRuleManager.TableSpec().Insert(ctx, secrule)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SecurityGroupRuleManager.Insert")
|
||||
return nil, isNeedFix, errors.Wrapf(err, "SecurityGroupRuleManager.Insert")
|
||||
}
|
||||
return secrule, nil
|
||||
return secrule, isNeedFix, nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroupRule) GetOwnerId() mcclient.IIdentityProvider {
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
"yunion.io/x/pkg/utils"
|
||||
@@ -95,8 +96,10 @@ func (manager *SSecurityGroupManager) ListItemFilter(
|
||||
return nil, httperrors.NewInputParameterError("Failed fetching secgroup %s", input.Equals)
|
||||
}
|
||||
secgroup := _secgroup.(*SSecurityGroup)
|
||||
inAllowList := secgroup.GetInAllowList()
|
||||
outAllowList := secgroup.GetOutAllowList()
|
||||
inAllowList, outAllowList, err := secgroup.GetAllowList()
|
||||
if err != nil {
|
||||
return q, httperrors.NewGeneralError(errors.Wrapf(err, "GetAllowList"))
|
||||
}
|
||||
sq := manager.Query().NotEquals("id", secgroup.Id)
|
||||
secgroups := []SSecurityGroup{}
|
||||
err = db.FetchModelObjects(manager, sq, &secgroups)
|
||||
@@ -105,12 +108,11 @@ func (manager *SSecurityGroupManager) ListItemFilter(
|
||||
}
|
||||
secgroupIds := []string{}
|
||||
for i := 0; i < len(secgroups); i++ {
|
||||
_inAllowList := secgroups[i].GetInAllowList()
|
||||
if !inAllowList.Equals(_inAllowList) {
|
||||
continue
|
||||
_inAllowList, _outAllowList, err := secgroups[i].GetAllowList()
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(errors.Wrapf(err, "GetAllowList"))
|
||||
}
|
||||
_outAllowList := secgroups[i].GetOutAllowList()
|
||||
if !outAllowList.Equals(_outAllowList) {
|
||||
if !inAllowList.Equals(_inAllowList) || !outAllowList.Equals(_outAllowList) {
|
||||
continue
|
||||
}
|
||||
secgroupIds = append(secgroupIds, secgroups[i].Id)
|
||||
@@ -515,7 +517,7 @@ func (self *SSecurityGroup) PostCreate(ctx context.Context, userCred mcclient.To
|
||||
|
||||
for _, r := range input.Rules {
|
||||
rule := &SSecurityGroupRule{
|
||||
Priority: int64(r.Priority),
|
||||
Priority: int64(*r.Priority),
|
||||
Protocol: r.Protocol,
|
||||
Ports: r.Ports,
|
||||
Direction: r.Direction,
|
||||
@@ -539,40 +541,61 @@ func (manager *SSecurityGroupManager) FetchSecgroupById(secId string) *SSecurity
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) getSecurityRules(direction string) (rules []SSecurityGroupRule) {
|
||||
func (self *SSecurityGroup) getSecurityRules() ([]SSecurityGroupRule, error) {
|
||||
secgrouprules := SecurityGroupRuleManager.Query().SubQuery()
|
||||
sql := secgrouprules.Query().Filter(sqlchemy.Equals(secgrouprules.Field("secgroup_id"), self.Id)).Desc("priority")
|
||||
if len(direction) > 0 && utils.IsInStringArray(direction, []string{"in", "out"}) {
|
||||
sql = sql.Equals("direction", direction)
|
||||
rules := []SSecurityGroupRule{}
|
||||
err := db.FetchModelObjects(SecurityGroupRuleManager, sql, &rules)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
if err := db.FetchModelObjects(SecurityGroupRuleManager, sql, &rules); err != nil {
|
||||
log.Errorf("GetGuests fail %s", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetSecRules(direction string) []secrules.SecurityRule {
|
||||
func (self *SSecurityGroup) GetSecuritRuleSet() (cloudprovider.SecurityRuleSet, error) {
|
||||
ruleSet := cloudprovider.SecurityRuleSet{}
|
||||
rules, err := self.getSecurityRules()
|
||||
if err != nil {
|
||||
return ruleSet, errors.Wrapf(err, "getSecurityRules")
|
||||
}
|
||||
for i := range rules {
|
||||
//这里没必要拆分为单个单个的端口,到公有云那边适配
|
||||
rule, err := rules[i].toRule()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "toRule")
|
||||
}
|
||||
ruleSet = append(ruleSet, cloudprovider.SecurityRule{SecurityRule: *rule, ExternalId: rules[i].Id})
|
||||
}
|
||||
return ruleSet, nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetSecRules() ([]secrules.SecurityRule, error) {
|
||||
rules := make([]secrules.SecurityRule, 0)
|
||||
for _, _rule := range self.getSecurityRules(direction) {
|
||||
_rules, err := self.getSecurityRules()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "getSecurityRules()")
|
||||
}
|
||||
for _, _rule := range _rules {
|
||||
//这里没必要拆分为单个单个的端口,到公有云那边适配
|
||||
rule, err := _rule.toRule()
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
continue
|
||||
return nil, errors.Wrapf(err, "toRule")
|
||||
}
|
||||
rules = append(rules, *rule)
|
||||
}
|
||||
return rules
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) getSecurityRuleString(direction string) string {
|
||||
secgrouprules := self.getSecurityRules(direction)
|
||||
func (self *SSecurityGroup) getSecurityRuleString() (string, error) {
|
||||
secgrouprules, err := self.getSecurityRules()
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "getSecurityRules()")
|
||||
}
|
||||
var rules []string
|
||||
for _, rule := range secgrouprules {
|
||||
rules = append(rules, rule.String())
|
||||
}
|
||||
return strings.Join(rules, SECURITY_GROUP_SEPARATOR)
|
||||
return strings.Join(rules, SECURITY_GROUP_SEPARATOR), nil
|
||||
}
|
||||
|
||||
func totalSecurityGroupCount(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider) (int, error) {
|
||||
@@ -735,7 +758,10 @@ func (self *SSecurityGroup) PerformClone(ctx context.Context, userCred mcclient.
|
||||
return input, httperrors.NewGeneralError(errors.Wrapf(err, "Insert"))
|
||||
}
|
||||
|
||||
secgrouprules := self.getSecurityRules("")
|
||||
secgrouprules, err := self.getSecurityRules()
|
||||
if err != nil {
|
||||
return input, httperrors.NewGeneralError(errors.Wrapf(err, "getSecurityRules"))
|
||||
}
|
||||
for _, rule := range secgrouprules {
|
||||
secgrouprule := &SSecurityGroupRule{}
|
||||
secgrouprule.SetModelManager(SecurityGroupRuleManager, secgrouprule)
|
||||
@@ -772,8 +798,10 @@ func (self *SSecurityGroup) PerformMerge(ctx context.Context, userCred mcclient.
|
||||
if len(input.SecgroupIds) == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("secgroup_ids")
|
||||
}
|
||||
inAllowList := self.GetInAllowList()
|
||||
outAllowList := self.GetOutAllowList()
|
||||
inAllowList, outAllowList, err := self.GetAllowList()
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(errors.Wrapf(err, "GetAllowList"))
|
||||
}
|
||||
secgroups := []*SSecurityGroup{}
|
||||
for _, secgroupId := range input.SecgroupIds {
|
||||
_secgroup, err := SecurityGroupManager.FetchByIdOrName(userCred, secgroupId)
|
||||
@@ -785,11 +813,13 @@ func (self *SSecurityGroup) PerformMerge(ctx context.Context, userCred mcclient.
|
||||
}
|
||||
secgroup := _secgroup.(*SSecurityGroup)
|
||||
secgroup.SetModelManager(SecurityGroupManager, secgroup)
|
||||
_inAllowList := secgroup.GetInAllowList()
|
||||
_inAllowList, _outAllowList, err := secgroup.GetAllowList()
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(errors.Wrapf(err, "GetAllowList"))
|
||||
}
|
||||
if !inAllowList.Equals(_inAllowList) {
|
||||
return nil, httperrors.NewUnsupportOperationError("secgroup %s rules not equals %s rules", secgroup.Name, self.Name)
|
||||
}
|
||||
_outAllowList := secgroup.GetOutAllowList()
|
||||
if !outAllowList.Equals(_outAllowList) {
|
||||
return nil, httperrors.NewUnsupportOperationError("secgroup %s rules not equals %s rules", secgroup.Name, self.Name)
|
||||
}
|
||||
@@ -813,27 +843,20 @@ func (self *SSecurityGroup) PerformMerge(ctx context.Context, userCred mcclient.
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetOutAllowList() secrules.SecurityRuleSet {
|
||||
rules := self.GetSecRules("out")
|
||||
ruleSet := secrules.SecurityRuleSet(rules)
|
||||
rules = append(rules, *secrules.MustParseSecurityRule("out:allow any"))
|
||||
return ruleSet.AllowList()
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetInAllowList() secrules.SecurityRuleSet {
|
||||
rules := self.GetSecRules("in")
|
||||
rules = append(rules, *secrules.MustParseSecurityRule("in:deny any"))
|
||||
ruleSet := secrules.SecurityRuleSet(rules)
|
||||
return ruleSet.AllowList()
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) getSecurityGroupRuleSet() secrules.SecurityGroupRuleSet {
|
||||
rules := self.GetSecRules("")
|
||||
srs := secrules.SecurityGroupRuleSet{}
|
||||
for i := 0; i < len(rules); i++ {
|
||||
srs.AddRule(rules[i])
|
||||
func (self *SSecurityGroup) GetAllowList() (secrules.SecurityRuleSet, secrules.SecurityRuleSet, error) {
|
||||
in, out := secrules.SecurityRuleSet{*secrules.MustParseSecurityRule("in:deny any")}, secrules.SecurityRuleSet{*secrules.MustParseSecurityRule("out:allow any")}
|
||||
rules, err := self.GetSecRules()
|
||||
if err != nil {
|
||||
return in, out, errors.Wrapf(err, "GetSecRules")
|
||||
}
|
||||
return srs
|
||||
for i := range rules {
|
||||
if rules[i].Direction == secrules.DIR_IN {
|
||||
in = append(in, rules[i])
|
||||
} else {
|
||||
in = append(in, rules[i])
|
||||
}
|
||||
}
|
||||
return in.AllowList(), out.AllowList(), nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) mergeSecurityGroupCache(secgroup *SSecurityGroup) error {
|
||||
@@ -892,94 +915,81 @@ func (manager *SSecurityGroupManager) getSecurityGroups() ([]SSecurityGroup, err
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) cleanRules(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
func (self *SSecurityGroup) removeRules(ruleIds []string, result *compare.SyncResult) {
|
||||
if len(ruleIds) == 0 {
|
||||
return
|
||||
}
|
||||
rules := []SSecurityGroupRule{}
|
||||
q := SecurityGroupRuleManager.Query().Equals("secgroup_id", self.Id)
|
||||
q := SecurityGroupRuleManager.Query().In("id", ruleIds)
|
||||
err := db.FetchModelObjects(SecurityGroupRuleManager, q, &rules)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "db.FetchModelObjects")
|
||||
result.DeleteError(errors.Wrapf(err, "db.FetchModelObjects"))
|
||||
return
|
||||
}
|
||||
for i := range rules {
|
||||
err = rules[i].Delete(ctx, userCred)
|
||||
err = rules[i].Delete(context.TODO(), nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "DeleteRule(%s)", rules[i].Id)
|
||||
result.DeleteError(errors.Wrapf(err, "delte rule %s", rules[i].Id))
|
||||
continue
|
||||
}
|
||||
result.Delete()
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) SyncSecurityGroupRules(ctx context.Context, userCred mcclient.TokenCredential, src cloudprovider.SecRuleInfo) ([]SSecurityGroupRule, compare.SyncResult) {
|
||||
result := compare.SyncResult{}
|
||||
localRules, err := self.GetSecuritRuleSet()
|
||||
if err != nil {
|
||||
result.Error(errors.Wrapf(err, "GetSecuritRuleSet"))
|
||||
return nil, result
|
||||
}
|
||||
|
||||
dest := cloudprovider.NewSecRuleInfo(GetRegionDriver(api.CLOUD_PROVIDER_ONECLOUD))
|
||||
dest.Rules = localRules
|
||||
|
||||
_, inAdds, outAdds, inDels, outDels := cloudprovider.CompareRules(src, dest, false)
|
||||
if len(inAdds)+len(inDels)+len(outAdds)+len(outDels) == 0 {
|
||||
return nil, result
|
||||
}
|
||||
|
||||
ruleIds := []string{}
|
||||
for _, dels := range [][]cloudprovider.SecurityRule{inDels, outDels} {
|
||||
for i := range dels {
|
||||
if len(dels[i].ExternalId) > 0 {
|
||||
ruleIds = append(ruleIds, dels[i].ExternalId)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) SyncSecurityGroupRules(ctx context.Context, userCred mcclient.TokenCredential, info *sRuleInfo) error {
|
||||
inRules := cloudprovider.AddDefaultRule(info.inRules, info.defaultInRule, "in:deny any", info.order, info.minPriority, info.maxPriority, info.onlyAllowRules)
|
||||
cloudprovider.SortSecurityRule(inRules, info.order, info.onlyAllowRules)
|
||||
outRules := cloudprovider.AddDefaultRule(info.outRules, info.defaultOutRule, "out:allow any", info.order, info.minPriority, info.maxPriority, info.onlyAllowRules)
|
||||
cloudprovider.SortSecurityRule(outRules, info.order, info.onlyAllowRules)
|
||||
self.removeRules(ruleIds, &result)
|
||||
|
||||
err := self.cleanRules(ctx, userCred)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "cleanRules")
|
||||
}
|
||||
|
||||
err = self.SyncRules(ctx, userCred, inRules)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "SyncInRules")
|
||||
}
|
||||
err = self.SyncRules(ctx, userCred, outRules)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "SyncOutRules")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type sRuleInfo struct {
|
||||
rules []cloudprovider.SecurityRule
|
||||
inRules []cloudprovider.SecurityRule
|
||||
outRules []cloudprovider.SecurityRule
|
||||
defaultInRule cloudprovider.SecurityRule
|
||||
defaultOutRule cloudprovider.SecurityRule
|
||||
order cloudprovider.TPriorityOrder
|
||||
onlyAllowRules bool
|
||||
maxPriority int
|
||||
minPriority int
|
||||
}
|
||||
|
||||
func (manager *SSecurityGroupManager) getRuleInfo(provider *SCloudprovider, extSec cloudprovider.ICloudSecurityGroup) (*sRuleInfo, error) {
|
||||
regionDriver, err := provider.GetRegionDriver()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "provider.GetRegionDriver")
|
||||
}
|
||||
|
||||
rules, err := extSec.GetRules()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "extSec.GetRules")
|
||||
}
|
||||
|
||||
info := &sRuleInfo{
|
||||
rules: rules,
|
||||
inRules: []cloudprovider.SecurityRule{},
|
||||
outRules: []cloudprovider.SecurityRule{},
|
||||
defaultInRule: regionDriver.GetDefaultSecurityGroupInRule(),
|
||||
defaultOutRule: regionDriver.GetDefaultSecurityGroupOutRule(),
|
||||
order: regionDriver.GetSecurityGroupRuleOrder(),
|
||||
onlyAllowRules: regionDriver.IsOnlySupportAllowRules(),
|
||||
maxPriority: regionDriver.GetSecurityGroupRuleMaxPriority(),
|
||||
minPriority: regionDriver.GetSecurityGroupRuleMinPriority(),
|
||||
}
|
||||
|
||||
for i := range rules {
|
||||
if rules[i].Direction == secrules.DIR_IN {
|
||||
info.inRules = append(info.inRules, rules[i])
|
||||
} else {
|
||||
info.outRules = append(info.outRules, rules[i])
|
||||
rules := []SSecurityGroupRule{}
|
||||
for _, adds := range [][]cloudprovider.SecurityRule{inAdds, outAdds} {
|
||||
for i := range adds {
|
||||
rule, isNeedFix, err := self.newFromCloudSecurityGroupRule(ctx, userCred, adds[i])
|
||||
if err != nil {
|
||||
result.AddError(errors.Wrapf(err, "newFromCloudSecurityGroupRule"))
|
||||
continue
|
||||
}
|
||||
if isNeedFix && rule != nil {
|
||||
rules = append(rules, *rule)
|
||||
}
|
||||
result.Add()
|
||||
}
|
||||
}
|
||||
return info, nil
|
||||
|
||||
log.Infof("Sync Rules for Secgroup %s(%s) result: %s", self.Name, self.Id, result.Result())
|
||||
return rules, result
|
||||
}
|
||||
|
||||
func (manager *SSecurityGroupManager) newFromCloudSecgroup(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, extSec cloudprovider.ICloudSecurityGroup) (*SSecurityGroup, error) {
|
||||
info, err := manager.getRuleInfo(provider, extSec)
|
||||
func (manager *SSecurityGroupManager) newFromCloudSecgroup(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, extSec cloudprovider.ICloudSecurityGroup) (*SSecurityGroup, []SSecurityGroupRule, error) {
|
||||
dest := cloudprovider.NewSecRuleInfo(GetRegionDriver(provider.Provider))
|
||||
var err error
|
||||
dest.Rules, err = extSec.GetRules()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "getRuleInfo")
|
||||
return nil, nil, errors.Wrapf(err, "extSec.GetRules")
|
||||
}
|
||||
src := cloudprovider.NewSecRuleInfo(GetRegionDriver(api.CLOUD_PROVIDER_ONECLOUD))
|
||||
|
||||
if options.Options.EnableAutoMergeSecurityGroup {
|
||||
// 查询与provider在同域的安全组,比对寻找一个与云上安全组规则相同的安全组
|
||||
@@ -987,13 +997,17 @@ func (manager *SSecurityGroupManager) newFromCloudSecgroup(ctx context.Context,
|
||||
q := manager.Query().Equals("domain_id", provider.DomainId)
|
||||
err = db.FetchModelObjects(manager, q, &secgroups)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "db.FetchModelObjects")
|
||||
return nil, nil, errors.Wrap(err, "db.FetchModelObjects")
|
||||
}
|
||||
for i := range secgroups {
|
||||
localRules := secrules.SecurityRuleSet(secgroups[i].GetSecRules(""))
|
||||
_, inAdds, outAdds, inDels, outDels := cloudprovider.CompareRules(info.minPriority, info.maxPriority, info.order, localRules, info.rules, info.defaultInRule, info.defaultOutRule, info.onlyAllowRules, false)
|
||||
src.Rules, err = secgroups[i].GetSecuritRuleSet()
|
||||
if err != nil {
|
||||
log.Warningf("GetSecuritRuleSet %s(%s) error: %v", secgroups[i].Name, secgroups[i].Id, err)
|
||||
continue
|
||||
}
|
||||
_, inAdds, outAdds, inDels, outDels := cloudprovider.CompareRules(src, dest, false)
|
||||
if len(inAdds) == 0 && len(outAdds) == 0 && len(inDels) == 0 && len(outDels) == 0 {
|
||||
return &secgroups[i], nil
|
||||
return &secgroups[i], nil, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1005,7 +1019,7 @@ func (manager *SSecurityGroupManager) newFromCloudSecgroup(ctx context.Context,
|
||||
secgroup.SetModelManager(manager, &secgroup)
|
||||
secgroup.Name, err = db.GenerateName(manager, userCred, extSec.GetName())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
secgroup.Status = api.SECGROUP_STATUS_READY
|
||||
@@ -1015,16 +1029,13 @@ func (manager *SSecurityGroupManager) newFromCloudSecgroup(ctx context.Context,
|
||||
|
||||
err = manager.TableSpec().Insert(ctx, &secgroup)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Insert")
|
||||
return nil, nil, errors.Wrapf(err, "Insert")
|
||||
}
|
||||
|
||||
err = secgroup.SyncSecurityGroupRules(ctx, userCred, info)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SyncSecurityGroupRules")
|
||||
}
|
||||
rules, _ := secgroup.SyncSecurityGroupRules(ctx, userCred, dest)
|
||||
|
||||
db.OpsLog.LogEvent(&secgroup, db.ACT_CREATE, secgroup.GetShortDesc(ctx), userCred)
|
||||
return &secgroup, nil
|
||||
return &secgroup, rules, nil
|
||||
}
|
||||
|
||||
func (manager *SSecurityGroupManager) DelaySync(ctx context.Context, userCred mcclient.TokenCredential, idStr string) {
|
||||
@@ -1223,6 +1234,9 @@ func (self *SSecurityGroup) AllowPerformImportRules(ctx context.Context, userCre
|
||||
|
||||
func (self *SSecurityGroup) PerformImportRules(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.SecgroupImportRulesInput) (jsonutils.JSONObject, error) {
|
||||
for i := range input.Rules {
|
||||
if input.Rules[i].Priority == nil {
|
||||
return nil, httperrors.NewMissingParameterError("priority")
|
||||
}
|
||||
err := input.Rules[i].Check()
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("rule %d is invalid: %s", i+1, err)
|
||||
@@ -1230,7 +1244,7 @@ func (self *SSecurityGroup) PerformImportRules(ctx context.Context, userCred mcc
|
||||
}
|
||||
for _, r := range input.Rules {
|
||||
rule := &SSecurityGroupRule{
|
||||
Priority: int64(r.Priority),
|
||||
Priority: int64(*r.Priority),
|
||||
Protocol: r.Protocol,
|
||||
Ports: r.Ports,
|
||||
Direction: r.Direction,
|
||||
|
||||
@@ -88,8 +88,9 @@ type SServerSku struct {
|
||||
PrepaidStatus string `width:"32" charset:"utf8" nullable:"true" list:"user" create:"admin_optional" default:"available"` // 预付费资源状态 available|soldout
|
||||
PostpaidStatus string `width:"32" charset:"utf8" nullable:"true" list:"user" create:"admin_optional" default:"available"` // 按需付费资源状态 available|soldout
|
||||
|
||||
CpuCoreCount int `nullable:"false" list:"user" create:"admin_required"`
|
||||
MemorySizeMB int `nullable:"false" list:"user" create:"admin_required"`
|
||||
CpuArch string `width:"16" charset:"ascii" nullable:"true" list:"user" create:"admin_optional" update:"admin"` // CPU 架构 x86|xarm
|
||||
CpuCoreCount int `nullable:"false" list:"user" create:"admin_required"`
|
||||
MemorySizeMB int `nullable:"false" list:"user" create:"admin_required"`
|
||||
|
||||
OsName string `width:"32" charset:"ascii" nullable:"true" list:"user" create:"admin_optional" update:"admin" default:"Any"` // Windows|Linux|Any
|
||||
|
||||
@@ -834,7 +835,7 @@ func (manager *SServerSkuManager) ListItemFilter(
|
||||
conditions = append(
|
||||
conditions,
|
||||
sqlchemy.AND(
|
||||
sqlchemy.GE(q.Field("memory_size_mb"), s),
|
||||
sqlchemy.GT(q.Field("memory_size_mb"), s),
|
||||
sqlchemy.LE(q.Field("memory_size_mb"), e),
|
||||
),
|
||||
)
|
||||
@@ -1171,6 +1172,7 @@ func (self *SServerSku) syncWithCloudSku(ctx context.Context, userCred mcclient.
|
||||
self.InstanceTypeCategory = extSku.InstanceTypeCategory
|
||||
self.PrepaidStatus = extSku.PrepaidStatus
|
||||
self.PostpaidStatus = extSku.PostpaidStatus
|
||||
self.CpuArch = extSku.CpuArch
|
||||
self.SysDiskType = extSku.SysDiskType
|
||||
self.DataDiskTypes = extSku.DataDiskTypes
|
||||
return nil
|
||||
|
||||
@@ -621,6 +621,10 @@ func (self *SSnapshot) ValidateDeleteCondition(ctx context.Context) error {
|
||||
if self.Status == api.SNAPSHOT_DELETING {
|
||||
return httperrors.NewBadRequestError("Cannot delete snapshot in status %s", self.Status)
|
||||
}
|
||||
return self.ValidatePurgeCondition(ctx)
|
||||
}
|
||||
|
||||
func (self *SSnapshot) ValidatePurgeCondition(ctx context.Context) error {
|
||||
count, err := InstanceSnapshotJointManager.Query().Equals("snapshot_id", self.Id).CountWithError()
|
||||
if err != nil {
|
||||
return httperrors.NewInternalServerError("Fetch instance snapshot error %s", err)
|
||||
|
||||
@@ -28,10 +28,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
syncSecgroupWorker *appsrv.SWorkerManager
|
||||
syncAccountWorker *appsrv.SWorkerManager
|
||||
syncWorkers []*appsrv.SWorkerManager
|
||||
syncWorkerRing *hashring.HashRing
|
||||
syncAccountWorker *appsrv.SWorkerManager
|
||||
syncWorkers []*appsrv.SWorkerManager
|
||||
syncWorkerRing *hashring.HashRing
|
||||
)
|
||||
|
||||
func InitSyncWorkers(count int) {
|
||||
@@ -53,12 +52,6 @@ func InitSyncWorkers(count int) {
|
||||
2048,
|
||||
true,
|
||||
)
|
||||
syncSecgroupWorker = appsrv.NewWorkerManager(
|
||||
"syncSecgroupProbeWorkerManager",
|
||||
1,
|
||||
2048,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
func RunSyncCloudproviderRegionTask(ctx context.Context, key string, syncFunc func()) {
|
||||
@@ -75,9 +68,3 @@ func RunSyncCloudAccountTask(ctx context.Context, probeFunc func()) {
|
||||
panicutils.SendPanicMessage(ctx, err)
|
||||
})
|
||||
}
|
||||
|
||||
func RunSyncSecgroupTask(ctx context.Context, syncFunc func()) {
|
||||
syncSecgroupWorker.Run(syncFunc, nil, func(err error) {
|
||||
panicutils.SendPanicMessage(ctx, err)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -15,13 +15,17 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/log"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/i18n"
|
||||
"yunion.io/x/onecloud/pkg/util/bitmap"
|
||||
)
|
||||
|
||||
@@ -159,6 +163,134 @@ func checkTimerCreateInput(in api.TimerCreateInput) (api.TimerCreateInput, error
|
||||
return in, nil
|
||||
}
|
||||
|
||||
var (
|
||||
timerDescTable = i18n.Table{}
|
||||
TIMERLANG = "timerLang"
|
||||
)
|
||||
|
||||
func init() {
|
||||
timerDescTable.Set("timerLang", i18n.NewTableEntry().EN("en").CN("cn"))
|
||||
}
|
||||
|
||||
func (st *STimer) Description(ctx context.Context) string {
|
||||
lang := timerDescTable.Lookup(ctx, TIMERLANG)
|
||||
switch lang {
|
||||
case "en":
|
||||
return st.descEnglish()
|
||||
case "cn":
|
||||
return st.descChinese()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var (
|
||||
wdsCN = []string{"", "一", "二", "三", "四", "五", "六", "日"}
|
||||
wdsEN = []string{"", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}
|
||||
zone = time.Now().Local().Location()
|
||||
//zone = time.FixedZone("GMT", 8*3600)
|
||||
)
|
||||
|
||||
func (st *STimer) descChinese() string {
|
||||
format := "2006-01-02 15:04:05"
|
||||
var prefix string
|
||||
switch st.Type {
|
||||
case api.TIMER_TYPE_ONCE:
|
||||
return fmt.Sprintf("单次 %s触发", st.StartTime.In(zone).Format(format))
|
||||
case api.TIMER_TYPE_DAY:
|
||||
prefix = "每天"
|
||||
case api.TIMER_TYPE_WEEK:
|
||||
wds := st.GetWeekDays()
|
||||
weekDays := make([]string, len(wds))
|
||||
for i := range wds {
|
||||
weekDays[i] = fmt.Sprintf("星期%s", wdsCN[wds[i]])
|
||||
}
|
||||
prefix = fmt.Sprintf("每周 【%s】", strings.Join(weekDays, "|"))
|
||||
case api.TIMER_TYPE_MONTH:
|
||||
mns := st.GetMonthDays()
|
||||
monthDays := make([]string, len(mns))
|
||||
for i := range mns {
|
||||
monthDays[i] = fmt.Sprintf("%d号", mns[i])
|
||||
}
|
||||
prefix = fmt.Sprintf("每月 【%s】", strings.Join(monthDays, "|"))
|
||||
}
|
||||
return fmt.Sprintf("%s %02d:%02d触发 有效时间为%s至%s", prefix, st.Hour, st.Minute, st.StartTime.In(zone).Format(format), st.EndTime.In(zone).Format(format))
|
||||
}
|
||||
|
||||
func (st *STimer) descEnglish() string {
|
||||
var detail string
|
||||
format := "2006-01-02 15:04:05"
|
||||
switch st.Type {
|
||||
case api.TIMER_TYPE_ONCE:
|
||||
return st.EndTime.In(zone).Format(format)
|
||||
case api.TIMER_TYPE_DAY:
|
||||
detail = fmt.Sprintf("%d:%d every day", st.Hour, st.Minute)
|
||||
case api.TIMER_TYPE_WEEK:
|
||||
detail = st.weekDaysDesc()
|
||||
case api.TIMER_TYPE_MONTH:
|
||||
detail = st.monthDaysDesc()
|
||||
}
|
||||
if st.EndTime.IsZero() {
|
||||
return detail
|
||||
}
|
||||
return fmt.Sprintf("%s, from %s to %s", detail, st.StartTime.In(zone).Format(format), st.EndTime.In(zone).Format(format))
|
||||
}
|
||||
|
||||
func (st *STimer) weekDaysDesc() string {
|
||||
if st.WeekDays == 0 {
|
||||
return ""
|
||||
}
|
||||
var desc strings.Builder
|
||||
wds := st.GetWeekDays()
|
||||
i := 0
|
||||
desc.WriteString(fmt.Sprintf("%d:%d every %s", st.Hour, st.Minute, wdsEN[wds[i]]))
|
||||
for i++; i < len(wds)-1; i++ {
|
||||
desc.WriteString(", ")
|
||||
desc.WriteString(wdsEN[wds[i]])
|
||||
}
|
||||
if i == len(wds)-1 {
|
||||
desc.WriteString(" and ")
|
||||
desc.WriteString(wdsEN[wds[i]])
|
||||
}
|
||||
return desc.String()
|
||||
}
|
||||
|
||||
func (st *STimer) monthDaysDesc() string {
|
||||
if st.MonthDays == 0 {
|
||||
return ""
|
||||
}
|
||||
var desc strings.Builder
|
||||
mds := st.GetMonthDays()
|
||||
i := 0
|
||||
desc.WriteString(fmt.Sprintf("%d:%d on the %d%s", st.Hour, st.Minute, mds[i], st.dateSuffix(mds[i])))
|
||||
for i++; i < len(mds)-1; i++ {
|
||||
desc.WriteString(", ")
|
||||
desc.WriteString(strconv.Itoa(mds[i]))
|
||||
desc.WriteString(st.dateSuffix(mds[i]))
|
||||
}
|
||||
if i == len(mds)-1 {
|
||||
desc.WriteString(" and ")
|
||||
desc.WriteString(strconv.Itoa(mds[i]))
|
||||
desc.WriteString(st.dateSuffix(mds[i]))
|
||||
}
|
||||
desc.WriteString(" of each month")
|
||||
return desc.String()
|
||||
}
|
||||
|
||||
func (st *STimer) dateSuffix(date int) string {
|
||||
var ret string
|
||||
switch date {
|
||||
case 1:
|
||||
ret = "st"
|
||||
case 2:
|
||||
ret = "nd"
|
||||
case 3:
|
||||
ret = "rd"
|
||||
default:
|
||||
ret = "th"
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func checkCycleTimerCreateInput(in api.CycleTimerCreateInput) (api.CycleTimerCreateInput, error) {
|
||||
now := time.Now()
|
||||
if in.Minute < 0 || in.Minute > 59 {
|
||||
|
||||
@@ -16,7 +16,6 @@ package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
@@ -26,6 +25,7 @@ import (
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
@@ -46,19 +46,6 @@ type SVpcResourceBaseManager struct {
|
||||
SManagedResourceBaseManager
|
||||
}
|
||||
|
||||
func ValidateVpcResourceInput(userCred mcclient.TokenCredential, input api.VpcResourceInput) (*SVpc, api.VpcResourceInput, error) {
|
||||
vpcObj, err := VpcManager.FetchByIdOrName(userCred, input.VpcId)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, input, httperrors.NewResourceNotFoundError2(VpcManager.Keyword(), input.VpcId)
|
||||
} else {
|
||||
return nil, input, errors.Wrap(err, "VpcManager.FetchByIdOrName")
|
||||
}
|
||||
}
|
||||
input.VpcId = vpcObj.GetId()
|
||||
return vpcObj.(*SVpc), input, nil
|
||||
}
|
||||
|
||||
func (self *SVpcResourceBase) GetVpc() *SVpc {
|
||||
obj, _ := VpcManager.FetchById(self.VpcId)
|
||||
if obj == nil {
|
||||
@@ -180,11 +167,16 @@ func (manager *SVpcResourceBaseManager) ListItemFilter(
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
if len(query.VpcId) > 0 {
|
||||
vpcObj, _, err := ValidateVpcResourceInput(userCred, query.VpcResourceInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "ValidateVpcResourceInput")
|
||||
switch query.VpcId {
|
||||
case api.CLASSIC_VPC_NAME:
|
||||
q = q.Equals("name", api.CLASSIC_VPC_NAME)
|
||||
default:
|
||||
_, err := validators.ValidateModel(userCred, VpcManager, &query.VpcId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q = q.Equals("vpc_id", query.VpcId)
|
||||
}
|
||||
q = q.Equals("vpc_id", vpcObj.GetId())
|
||||
}
|
||||
subq := VpcManager.Query("id").Snapshot()
|
||||
subq, err = manager.SCloudregionResourceBaseManager.ListItemFilter(ctx, subq, userCred, query.RegionalFilterListInput)
|
||||
|
||||
@@ -287,7 +287,7 @@ func (manager *SVpcManager) GetOrCreateVpcForClassicNetwork(ctx context.Context,
|
||||
vpc.IsDefault = false
|
||||
vpc.CloudregionId = region.Id
|
||||
vpc.SetModelManager(manager, vpc)
|
||||
vpc.Name = "-"
|
||||
vpc.Name = api.CLASSIC_VPC_NAME
|
||||
vpc.IsEmulated = true
|
||||
vpc.SetEnabled(false)
|
||||
vpc.Status = api.VPC_STATUS_UNAVAILABLE
|
||||
@@ -1417,7 +1417,7 @@ func (manager *SVpcManager) ListItemExportKeys(ctx context.Context,
|
||||
if keys.Contains("wire_count") {
|
||||
wires := WireManager.Query("vpc_id").SubQuery()
|
||||
subq := wires.Query(sqlchemy.COUNT("wire_count"), wires.Field("vpc_id")).GroupBy(wires.Field("vpc_id")).SubQuery()
|
||||
q = q.Join(subq, sqlchemy.Equals(q.Field("id"), subq.Field("vpc_id")))
|
||||
q = q.LeftJoin(subq, sqlchemy.Equals(q.Field("id"), subq.Field("vpc_id")))
|
||||
q = q.AppendField(subq.Field("wire_count"))
|
||||
}
|
||||
|
||||
@@ -1425,10 +1425,10 @@ func (manager *SVpcManager) ListItemExportKeys(ctx context.Context,
|
||||
wires := WireManager.Query("id", "vpc_id").SubQuery()
|
||||
networks := NetworkManager.Query("wire_id").SubQuery()
|
||||
subq := networks.Query(sqlchemy.COUNT("network_count"), wires.Field("vpc_id"))
|
||||
subq = subq.Join(wires, sqlchemy.Equals(networks.Field("wire_id"), wires.Field("id")))
|
||||
subq = subq.LeftJoin(wires, sqlchemy.Equals(networks.Field("wire_id"), wires.Field("id")))
|
||||
subq = subq.GroupBy(wires.Field("vpc_id"))
|
||||
subqQ := subq.SubQuery()
|
||||
q = q.Join(subqQ, sqlchemy.Equals(q.Field("id"), subqQ.Field("vpc_id")))
|
||||
q = q.LeftJoin(subqQ, sqlchemy.Equals(q.Field("id"), subqQ.Field("vpc_id")))
|
||||
q = q.AppendField(subqQ.Field("network_count"))
|
||||
}
|
||||
|
||||
|
||||
@@ -113,11 +113,11 @@ func (manager *SWireManager) ValidateCreateData(
|
||||
input.VpcId = api.DEFAULT_VPC_ID
|
||||
}
|
||||
|
||||
var vpc *SVpc
|
||||
vpc, input.VpcResourceInput, err = ValidateVpcResourceInput(userCred, input.VpcResourceInput)
|
||||
_vpc, err := validators.ValidateModel(userCred, VpcManager, &input.VpcId)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "ValidateVpcResourceInput")
|
||||
return input, err
|
||||
}
|
||||
vpc := _vpc.(*SVpc)
|
||||
|
||||
if len(vpc.ManagerId) > 0 {
|
||||
return input, httperrors.NewNotSupportedError("Currently only kvm platform supports creating wire")
|
||||
@@ -1012,6 +1012,10 @@ func (manager *SWireManager) ListItemFilter(
|
||||
q = q.Filter(sqlchemy.In(q.Field("id"), sq.SubQuery()))
|
||||
}
|
||||
|
||||
if query.Bandwidth != nil {
|
||||
q = q.Equals("bandwidth", *query.Bandwidth)
|
||||
}
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -149,7 +149,8 @@ type ComputeOptions struct {
|
||||
SyncStorageCapacityUsedIntervalMinutes int `help:"interval sync storage capacity used" default:"20"`
|
||||
LockStorageFromCachedimage bool `help:"must use storage in where selected cachedimage when creating vm"`
|
||||
|
||||
SyncExtDiskSnapshotIntervalMinutes int `help:"sync snapshot for external disk" default:"20"`
|
||||
SyncExtDiskSnapshotIntervalMinutes int `help:"sync snapshot for external disk" default:"20"`
|
||||
AutoReconcileBackupServers bool `help:"auto reconcile backup servers" default:"false"`
|
||||
|
||||
SCapabilityOptions
|
||||
SASControllerOptions
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user