mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
Automatic merge from release/2.3.0 -> release/2.4.0
* commit '42636c0b13bc9e2a77c0db40e9aeba8ae5f017bf': (120 commits) add GetAttachDiskStatus add more log security group add id tag security group sync upload image add aws toHOST_TYPES add aws scheduler api bugfix add host type mapping bugfix bugfix bugfix support aws china add azure metadatas add aliyun tag bugfix add aws tags read aws instance type from file add todo zone bugfix ...
This commit is contained in:
Generated
+217
-122
@@ -79,7 +79,7 @@
|
||||
version = "v1.19.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:5e9ea5618cb3451ce312505a48a563e95ce26c9ef498cd0a8833255e5e7f5c61"
|
||||
digest = "1:bad9acf125c8b98ea473f45cf8eabee4c401fcd108534b65d2033af7481be25d"
|
||||
name = "github.com/aliyun/alibaba-cloud-sdk-go"
|
||||
packages = [
|
||||
"sdk",
|
||||
@@ -93,8 +93,8 @@
|
||||
"sdk/utils",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "e61479d8220e534e78523e75ff42f92e8d5ac6e1"
|
||||
version = "1.31.0"
|
||||
revision = "1d757c22fbf7997c68c43d72e92d462ea05e1439"
|
||||
version = "0.7.4"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:5a2d4da3f703696f4bec1ba1d363f50461b72934b1817c07ab0963496ed1c90d"
|
||||
@@ -113,11 +113,57 @@
|
||||
version = "v1.0.1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:eee9386329f4fcdf8d6c0def0c9771b634bdd5ba460d888aa98c17d59b37a76c"
|
||||
digest = "1:e64acfe8cda1955db545ede8e863c54d69f1ac6cd058df4349be4040320840fd"
|
||||
name = "github.com/apache/thrift"
|
||||
packages = ["lib/go/thrift"]
|
||||
pruneopts = "UT"
|
||||
revision = "e59b73d3c2bf1c328ccb78e683c0462fa1a473c7"
|
||||
revision = "327ebb6c2b6df8bf075da02ef45a2a034e9b79ba"
|
||||
version = "0.11.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:55bf2a4da68caa693d660683e53bab3e651a940cd46354b997ab68bec7920e23"
|
||||
name = "github.com/aws/aws-sdk-go"
|
||||
packages = [
|
||||
"aws",
|
||||
"aws/awserr",
|
||||
"aws/awsutil",
|
||||
"aws/client",
|
||||
"aws/client/metadata",
|
||||
"aws/corehandlers",
|
||||
"aws/credentials",
|
||||
"aws/credentials/ec2rolecreds",
|
||||
"aws/credentials/endpointcreds",
|
||||
"aws/credentials/stscreds",
|
||||
"aws/csm",
|
||||
"aws/defaults",
|
||||
"aws/ec2metadata",
|
||||
"aws/endpoints",
|
||||
"aws/request",
|
||||
"aws/session",
|
||||
"aws/signer/v4",
|
||||
"internal/ini",
|
||||
"internal/s3err",
|
||||
"internal/sdkio",
|
||||
"internal/sdkrand",
|
||||
"internal/sdkuri",
|
||||
"internal/shareddefaults",
|
||||
"private/protocol",
|
||||
"private/protocol/ec2query",
|
||||
"private/protocol/eventstream",
|
||||
"private/protocol/eventstream/eventstreamapi",
|
||||
"private/protocol/query",
|
||||
"private/protocol/query/queryutil",
|
||||
"private/protocol/rest",
|
||||
"private/protocol/restxml",
|
||||
"private/protocol/xml/xmlutil",
|
||||
"service/ec2",
|
||||
"service/iam",
|
||||
"service/s3",
|
||||
"service/sts",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "cf00ea20983ce38df17ab0a0814463ab8838459f"
|
||||
version = "v1.15.73"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@@ -144,7 +190,7 @@
|
||||
version = "v0.2.1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:7205ab9c5433db402268526647efc47daa3236f9a85a1faba705fda12fdafd29"
|
||||
digest = "1:1c45e98df3726b24a0cc200f5ed182e5eefbe6a8cf2927f9d4335151aa190d15"
|
||||
name = "github.com/coredns/coredns"
|
||||
packages = [
|
||||
"core/dnsserver",
|
||||
@@ -186,6 +232,7 @@
|
||||
"plugin/pkg/response",
|
||||
"plugin/pkg/tls",
|
||||
"plugin/pkg/trace",
|
||||
"plugin/pkg/transport",
|
||||
"plugin/pkg/uniq",
|
||||
"plugin/pkg/up",
|
||||
"plugin/pkg/upstream",
|
||||
@@ -197,8 +244,8 @@
|
||||
"request",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "eb51e8bac90fac86d34c9e1cb89b04ea0936b034"
|
||||
version = "v1.2.2"
|
||||
revision = "756749c5cad4cd40453b82f70592bc19bb9ccb15"
|
||||
version = "v1.2.6"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec"
|
||||
@@ -258,11 +305,11 @@
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:a76c5e933af8688d9dcfbe718f2b0bfc955208fe0e47e74218b45f1df83ef2ae"
|
||||
digest = "1:26e2bfc6572da45d1bc22de65cbb4d47bf4ab191279719e7aed71f16b865d7db"
|
||||
name = "github.com/farsightsec/golang-framestream"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "d0f7ed81b7afcc56d3c1a66a0fd26a1b609675f3"
|
||||
revision = "8a0cb8ba87105c2d27e725e48e50ce0b5c521d57"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:865079840386857c809b72ce300be7580cb50d3d3129ce11bf9aa6ca2bc1934a"
|
||||
@@ -280,14 +327,6 @@
|
||||
pruneopts = "UT"
|
||||
revision = "3f9db97f856818214da2e1057f8ad84803971cff"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:2cd7915ab26ede7d95b8749e6b1f933f1c6d5398030684e6505940a10f31cfda"
|
||||
name = "github.com/ghodss/yaml"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:36fe9527deed01d2a317617e59304eb2c4ce9f8a24115bcc5c2e37b3aee5bae4"
|
||||
@@ -297,16 +336,15 @@
|
||||
revision = "22d885f9ecc78bf4ee5d72b937e4bbcdc58e8cae"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:ff09f03ca12c4d23c28c596eb0738745e36c1cac111f62f64819210f40607cd2"
|
||||
digest = "1:ab00ecdc9607692ffd5fb1ac21a9ba2d6cc95bae011f327022c0b1c323d218e2"
|
||||
name = "github.com/gin-gonic/gin"
|
||||
packages = [
|
||||
"binding",
|
||||
"json",
|
||||
"render",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "b869fe1415e4b9eb52f247441830d502aece2d4d"
|
||||
version = "v1.3.0"
|
||||
revision = "d459835d2b077e44f7c9b453505ee29881d5d12d"
|
||||
version = "v1.2"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:31a18dae27a29aa074515e43a443abfd2ba6deb6d69309d8d7ce789c45f34659"
|
||||
@@ -325,15 +363,15 @@
|
||||
version = "v1.4.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:34e709f36fd4f868fb00dbaf8a6cab4c1ae685832d392874ba9d7c5dec2429d1"
|
||||
digest = "1:b7a8552c62868d867795b63eaf4f45d3e92d36db82b428e680b9c95a8c33e5b1"
|
||||
name = "github.com/gogo/protobuf"
|
||||
packages = [
|
||||
"proto",
|
||||
"sortkeys",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "636bf0302bc95575d69441b25a2603156ffdddf1"
|
||||
version = "v1.1.1"
|
||||
revision = "342cbe0a04158f6dcb03ca0079991a51a4248c02"
|
||||
version = "v0.5"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:94d8c9e3a4954505ca89243e2121180972eecf8e3d160f3b34a48825ddd95cc1"
|
||||
@@ -361,15 +399,14 @@
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:1ba1d79f2810270045c328ae5d674321db34e3aae468eb4233883b473c5c0467"
|
||||
digest = "1:2edd2416f89b4e841df0e4a78802ce14d2bc7ad79eba1a45986e39f0f8cb7d87"
|
||||
name = "github.com/golang/glog"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998"
|
||||
revision = "44145f04b68cf362d9c4df2182967c2275eaefed"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:4c0989ca0bcd10799064318923b9bc2db6b4d6338dd75f3f2d86c3511aaaf5cf"
|
||||
digest = "1:17fe264ee908afc795734e8c4e63db2accabaf57326dbf21763a7d6b86096260"
|
||||
name = "github.com/golang/protobuf"
|
||||
packages = [
|
||||
"proto",
|
||||
@@ -379,8 +416,8 @@
|
||||
"ptypes/timestamp",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
|
||||
version = "v1.2.0"
|
||||
revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@@ -399,23 +436,21 @@
|
||||
revision = "4030bb1f1f0c35b30ca7009e9ebd06849dd45306"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:3ee90c0d94da31b442dde97c99635aaafec68d0b8a3c12ee2075c6bdabeec6bb"
|
||||
digest = "1:41bfd4219241b7f7d6e6fdb13fc712576f1337e68e6b895136283b76928fdd66"
|
||||
name = "github.com/google/gofuzz"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1"
|
||||
revision = "44d81051d367757e1c7c6a5a86423ece9afcf63c"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:3a26588bc48b96825977c1b3df964f8fd842cd6860cc26370588d3563433cf11"
|
||||
digest = "1:9f7a9e0b3f54aad2c053f778b9933263de723f6d722c68092b1eec06b95a5860"
|
||||
name = "github.com/google/uuid"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "d460ce9f8df2e77fb1ba55ca87fafed96c607494"
|
||||
version = "v1.0.0"
|
||||
revision = "7e072fc3a7be179aee6d3359e46015aa8c995314"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:65c4414eeb350c47b8de71110150d0ea8a281835b1f386eacaa3ad7325929c21"
|
||||
digest = "1:75eb87381d25cc75212f52358df9c3a2719584eaa9685cd510ce28699122f39d"
|
||||
name = "github.com/googleapis/gnostic"
|
||||
packages = [
|
||||
"OpenAPIv2",
|
||||
@@ -423,8 +458,7 @@
|
||||
"extensions",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "7c663266750e7d82587642f65e60bc4083f1f84e"
|
||||
version = "v0.2.0"
|
||||
revision = "0c5108395e2debce0d731cf0287ddf7242066aba"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@@ -443,11 +477,11 @@
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:8ec54d9488698e9db22139250bde10e35aab02c20236e4d1c1457604c2c4fe18"
|
||||
digest = "1:3eb026ba34d6dd12b45bb6abd63b4e917ebca8d8f3022a139c0881d900ad1bee"
|
||||
name = "github.com/googollee/go-socket.io"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "25e1f67559cf5d0e41efbc3e0157bb952596ffc3"
|
||||
revision = "c8aeb1ed9b49d7de8fef8662efb18f1d289c5f2e"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:c79fb010be38a59d657c48c6ba1d003a8aa651fa56b579d959d74573b7dff8e1"
|
||||
@@ -486,15 +520,14 @@
|
||||
revision = "36ee7e946282a3fb1cfecd476ddc9b35d8847e42"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:86c1210529e69d69860f2bb3ee9ccce0b595aa3f9165e7dd1388e5c612915888"
|
||||
digest = "1:878f0defa9b853f9acfaf4a162ba450a89d0050eff084f9fe7f5bd15948f172a"
|
||||
name = "github.com/gregjones/httpcache"
|
||||
packages = [
|
||||
".",
|
||||
"diskcache",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "9cad4c3443a7200dd6400aef47183728de563a38"
|
||||
revision = "787624de3eb7bd915c329cba748687a3b22666a6"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@@ -505,20 +538,20 @@
|
||||
revision = "8e809c8a86450a29b90dcc9efbf062d0fe6d9746"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:09970bb8daf100bdf11b48b72c71ef980cd2b50efbd903989b3d182956be0b83"
|
||||
name = "github.com/hako/durafmt"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "7b7ae1e72eade09dbc9c2cfba3e6c4bae7b8bcac"
|
||||
version = "1.0.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:8eb1de8112c9924d59bf1d3e5c26f5eaa2bfc2a5fcbb92dc1c2e4546d695f277"
|
||||
digest = "1:3e260afa138eab6492b531a3b3d10ab4cb70512d423faa78b8949dec76e66a21"
|
||||
name = "github.com/imdario/mergo"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "9f23e2d6bd2a77f959b2bf6acdbefd708a83a4a4"
|
||||
version = "v0.3.6"
|
||||
revision = "9316a62528ac99aaecb4e47eadd6dc8aa6533d58"
|
||||
version = "v0.3.5"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:b6f4477f09f11785097a121811f3a90d8d26cab73c1aa71abda859bdf6ad2334"
|
||||
@@ -540,28 +573,26 @@
|
||||
revision = "04140366298a54a039076d798123ffa108fff46c"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:b87714e57a511d88f307aba7d5b63522da12bed0a050889c81272fc50f71100e"
|
||||
digest = "1:e22af8c7518e1eab6f2eab2b7d7558927f816262586cd6ed9f349c97a6c285c4"
|
||||
name = "github.com/jmespath/go-jmespath"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "3433f3ea46d9f8019119e7dd41274e112a2359a9"
|
||||
version = "0.2.2"
|
||||
revision = "0b12d6b5"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:3e551bbb3a7c0ab2a2bf4660e7fcad16db089fdcfbb44b0199e62838038623ea"
|
||||
digest = "1:bb3cc4c1b21ea18cfa4e3e47440fc74d316ab25b0cf42927e8c1274917bd9891"
|
||||
name = "github.com/json-iterator/go"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "1624edc4454b8682399def8740d46db5e4362ba4"
|
||||
version = "v1.1.5"
|
||||
revision = "f2b4162afba35581b6d4a50d3b8f34e33c144682"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:f44d34fda864bed6d6c71514cd40b2ee097e6e67f745d5d014113e1faa5af8b7"
|
||||
digest = "1:0a69a1c0db3591fcefb47f115b224592c8dfa4368b7ba9fae509d5e16cdc95c8"
|
||||
name = "github.com/konsorten/go-windows-terminal-sequences"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "b729f2633dfe35f4d1d8a32385f6685610ce1cb5"
|
||||
revision = "5c8c8bd35d3832f5d134ae1e1e375b69a4d25242"
|
||||
version = "v1.0.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@@ -572,12 +603,12 @@
|
||||
revision = "b84e30acd515aadc4b783ad4ff83aff3299bdfe0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:29d28429a93b076908a36420a7ecb2bf429d24c15a4b5e2c220ea00fc84b71af"
|
||||
name = "github.com/kr/pty"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "db8e3cd836b82e82e0a9c8edc6896967dd31374f"
|
||||
version = "v1.1.3"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:4e878df5f4e9fd625bf9c9aac77ef7cbfa4a74c01265505527c23470c0e40300"
|
||||
@@ -604,12 +635,12 @@
|
||||
version = "v0.0.4"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:cdb899c199f907ac9fb50495ec71212c95cb5b0e0a8ee0800da0238036091033"
|
||||
name = "github.com/mattn/go-runewidth"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "ce7b0b5c7b45a81508558cd1dba6bb1e4ddb51bb"
|
||||
version = "v0.0.3"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@@ -649,12 +680,12 @@
|
||||
version = "v0.10.11"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:b39aee4261f1ae13fdd21a0db189e0bba0f96c0f2eba77ab278428e2d3b00052"
|
||||
digest = "1:b20d8767957e40b9302a8caaee88caa698513fbd972509a54555302c3aebfa04"
|
||||
name = "github.com/miekg/dns"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "f4db2ca6edc3af0ee51bf332099cc480bcf3ef9d"
|
||||
version = "v1.0.10"
|
||||
revision = "7064f7248f5fa5fd79382a76328b4e200b79e4ae"
|
||||
version = "v1.0.15"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:33422d238f147d247752996a26574ac48dcf472976eda7f5134015f06bf16563"
|
||||
@@ -665,12 +696,12 @@
|
||||
version = "1.0.3"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:e32bdbdb7c377a07a9a46378290059822efdce5c8d96fe71940d87cb4f918855"
|
||||
digest = "1:c56ad36f5722eb07926c979d5e80676ee007a9e39e7808577b9d87ec92b00460"
|
||||
name = "github.com/modern-go/reflect2"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd"
|
||||
version = "1.0.1"
|
||||
revision = "94122c33edd36123c84d5368cfb2b69df93a0ec8"
|
||||
version = "v1.0.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@@ -688,6 +719,14 @@
|
||||
pruneopts = "UT"
|
||||
revision = "9ac6cf4d929b2fa8fd2d2e6dec5bb0feb4f4911d"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:0d3513430f7d83565e9a6bc2727de8fa16f7103ef628b179fefc712590670e7e"
|
||||
name = "github.com/nelsonken/cos-go-sdk-v5"
|
||||
packages = ["cos"]
|
||||
pruneopts = "UT"
|
||||
revision = "5247afdb7a80666955f2b8b108772bf7af5031c8"
|
||||
version = "v1.21"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:2da0e5077ed40453dc281b9a2428d84cf6ad14063aed189f6296ca5dd25cf13d"
|
||||
@@ -740,23 +779,23 @@
|
||||
version = "v2.0.1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:4f0885b3f0dba96128a09a6f4b4231c42688fbd05f323224c6aa5adc9f4e87bf"
|
||||
digest = "1:e39a5ee8fcbec487f8fc68863ef95f2b025e0739b0e4aa55558a2b4cf8f0ecf0"
|
||||
name = "github.com/pierrec/lz4"
|
||||
packages = [
|
||||
".",
|
||||
"internal/xxh32",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "bb6bfd13c6a262f1943c0446eb25b7f54c1fb9a2"
|
||||
version = "v2.0.6"
|
||||
revision = "635575b42742856941dbc767b44905bb9ba083f6"
|
||||
version = "v2.0.7"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:4f43b3c1b7e44980a5f3c593f8bf0e18844dc44f451a071c93e77e28cf990db6"
|
||||
digest = "1:4cd499f102d1dbd7583f07431c8530b385f089c4b188a0778bc47a870930eb9b"
|
||||
name = "github.com/pkg/term"
|
||||
packages = ["termios"]
|
||||
pruneopts = "UT"
|
||||
revision = "bffc007b7fd5a70e20e28f5b7649bb84671ef436"
|
||||
revision = "93e6c91493094ff99a036fea0040802a1e0a4f69"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe"
|
||||
@@ -767,15 +806,16 @@
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:d14a5f4bfecf017cb780bdde1b6483e5deb87e12c332544d2c430eda58734bcb"
|
||||
digest = "1:26663fafdea73a38075b07e8e9d82fc0056379d2be8bb4e13899e8fda7c7dd23"
|
||||
name = "github.com/prometheus/client_golang"
|
||||
packages = [
|
||||
"prometheus",
|
||||
"prometheus/internal",
|
||||
"prometheus/promhttp",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "c5b7fccd204277076155f10851dad72b76a49317"
|
||||
version = "v0.8.0"
|
||||
revision = "abad2d1bd44235a26707c172eab6bca5bf2dbad3"
|
||||
version = "v0.9.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@@ -787,7 +827,7 @@
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:63b68062b8968092eb86bedc4e68894bd096ea6b24920faca8b9dcf451f54bb5"
|
||||
digest = "1:db712fde5d12d6cdbdf14b777f0c230f4ff5ab0be8e35b239fc319953ed577a4"
|
||||
name = "github.com/prometheus/common"
|
||||
packages = [
|
||||
"expfmt",
|
||||
@@ -795,11 +835,11 @@
|
||||
"model",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "c7de2306084e37d54b8be01f3541a8464345e9a5"
|
||||
revision = "0b1957f9d949dfa3084171a6ec5642b38055276a"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:ef1dd9945e58ee9b635273d28c0ef3fa3742a7dedc038ebe207fd63e6ce000ef"
|
||||
digest = "1:ef74914912f99c79434d9c09658274678bc85080ebe3ab32bec3940ebce5e1fc"
|
||||
name = "github.com/prometheus/procfs"
|
||||
packages = [
|
||||
".",
|
||||
@@ -808,15 +848,15 @@
|
||||
"xfs",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "418d78d0b9a7b7de3a6bbc8a23def624cc977bb2"
|
||||
revision = "185b4288413d2a0dd0806f78c90dde719829e5ae"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:c4556a44e350b50a490544d9b06e9fba9c286c21d6c0e47f54f3a9214597298c"
|
||||
digest = "1:d38f81081a389f1466ec98192cf9115a82158854d6f01e1c23e2e7554b97db71"
|
||||
name = "github.com/rcrowley/go-metrics"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "e2704e165165ec55d062f5919b4b29494e9fa790"
|
||||
revision = "3113b8401b8a98917cde58f8bbd42a1b1c03b1fd"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:274f67cb6fed9588ea2521ecdac05a6d62a8c51c074c1fccc6a49a40ba80e925"
|
||||
@@ -835,20 +875,20 @@
|
||||
revision = "49a4782e9908fe098c907022a1bd7519c79803d6"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:dc2d85c13ac22c22a1f3170a41a8e1b897fa05134aaf533f16df44f66a25b4a1"
|
||||
digest = "1:69b1cc331fca23d702bd72f860c6a647afd0aa9fcbc1d0659b1365e26546dd70"
|
||||
name = "github.com/sirupsen/logrus"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "a67f783a3814b8729bd2dac5780b5f78f8dbd64d"
|
||||
version = "v1.1.0"
|
||||
revision = "bcd833dfe83d3cebad139e4a29ed79cb2318bf95"
|
||||
version = "v1.2.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:dab83a1bbc7ad3d7a6ba1a1cc1760f25ac38cdf7d96a5cdd55cd915a4f5ceaf9"
|
||||
digest = "1:9424f440bba8f7508b69414634aef3b2b3a877e522d8a4624692412805407bb7"
|
||||
name = "github.com/spf13/pflag"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "9a97c102cda95a86cec2345a6f09f55a939babf5"
|
||||
version = "v1.0.2"
|
||||
revision = "583c0c0531f06d5278b7d917446061adc344b5cd"
|
||||
version = "v1.0.1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:18752d0b95816a1b777505a97f71c7467a8445b8ffb55631a7bf779f6ba4fa83"
|
||||
@@ -858,6 +898,19 @@
|
||||
revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686"
|
||||
version = "v1.2.2"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:a115409defa2eb9059f215a91573ac1126123c4feac6bbb8d97f05e2b7761fe2"
|
||||
name = "github.com/tencentcloud/tencentcloud-sdk-go"
|
||||
packages = [
|
||||
"tencentcloud/common",
|
||||
"tencentcloud/common/errors",
|
||||
"tencentcloud/common/http",
|
||||
"tencentcloud/common/profile",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "805d01dd0e2ef6e8ab69faf815c680e93c52c91a"
|
||||
version = "3.0.30"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:a38c75e7edd595bbaa03334c1ac26163a5e990d81f05cd9ec5fd0edc9c786078"
|
||||
@@ -879,15 +932,14 @@
|
||||
revision = "7d3ee1afa71c90fd1514c8f557ae6c5f414208eb"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:98e5cda86f67cd1ac95389d98670b66dea8cae480fe6292b83bccccfe60b4106"
|
||||
digest = "1:7b36ba7867ad2d262abedeff4c9362f2e8aa00cf6dd3254a509f24c27eb1d5b7"
|
||||
name = "github.com/ugorji/go"
|
||||
packages = ["codec"]
|
||||
pruneopts = "UT"
|
||||
revision = "f3cacc17c85ecb7f1b6a9e373ee85d1480919868"
|
||||
revision = "9c7f9b7a2bc3a520f7c7b30b34b7f85f47fe27b6"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:35f0192bdf8cdd76e1851c53e293c92c058c20870ccb0af1a292f5e64075fe40"
|
||||
digest = "1:506f2f0fee9b0e75b987286233a3b0d3fbf7cb145d754b0719b672822246cbc6"
|
||||
name = "github.com/vmware/govmomi"
|
||||
packages = [
|
||||
".",
|
||||
@@ -907,11 +959,12 @@
|
||||
"vim25/xml",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "c8ddb4b2bcda00a066d84c889dbb40d1aa9f2519"
|
||||
revision = "3617f28d167d448f93f282a867870f109516d2a5"
|
||||
version = "v0.19.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:71c5989353531072eeb9547066e05bdeaaf9ef0512673bca3b4b824092d70de3"
|
||||
digest = "1:9bca23e99b8dc02f7f22d197ee886acde6dd7c7a16855f1822ed78f362c2ff1b"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = [
|
||||
"curve25519",
|
||||
@@ -926,11 +979,11 @@
|
||||
"ssh/terminal",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "5295e8364332db77d75fce11f1d19c053919a9c9"
|
||||
revision = "e4dc69e5b2fd71dcaf8bd5d054eb936deb78d1fa"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:4ab551743538ce88c540073958b2fb653ca077c5d4c3d1991d86016dd38e22f6"
|
||||
digest = "1:81bd9a6bed3c32ef0c7350aca59f5cbd816b2e2a4cbde0eb5fdca60526be57e0"
|
||||
name = "golang.org/x/net"
|
||||
packages = [
|
||||
"bpf",
|
||||
@@ -947,18 +1000,28 @@
|
||||
"trace",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "4dfa2610cdf3b287375bbba5b8f2a14d3b01d8de"
|
||||
revision = "03003ca0c849e57b6ea29a4bab8d3cb6e4d568fe"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:9359217acc6040b4be710ce34473acef28023ad39bfafecea34ffaea7f1e1890"
|
||||
name = "golang.org/x/oauth2"
|
||||
packages = [
|
||||
".",
|
||||
"internal",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "a6bd8cefa1811bd24b86f8902872e4e8225f74c4"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:2c607ffa8a0a34a9acba4aba7b33d981b5a2150bfcec41b1f2ef1d791bcf6c14"
|
||||
digest = "1:6a875550c3b582f6c2d7e2ce44aba792511f00016d7c46b0a4fb26f730ef3058"
|
||||
name = "golang.org/x/sys"
|
||||
packages = [
|
||||
"unix",
|
||||
"windows",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "dad3d9fb7b6e83d0f9ac8f54670f6334c3a287b4"
|
||||
revision = "66b7b1311ac80bbafcd2daeef9a5e6e2cd1e2399"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18"
|
||||
@@ -984,20 +1047,28 @@
|
||||
version = "v0.3.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:c9e7a4b4d47c0ed205d257648b0e5b0440880cb728506e318f8ac7cd36270bc4"
|
||||
digest = "1:d37b0ef2944431fe9e8ef35c6fffc8990d9e2ca300588df94a6890f3649ae365"
|
||||
name = "golang.org/x/time"
|
||||
packages = ["rate"]
|
||||
pruneopts = "UT"
|
||||
revision = "fbb02b2291d28baffd63558aa44b4b56f178d650"
|
||||
revision = "f51c12702a4d776e4c1fa9b0fabab841babae631"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:c25289f43ac4a68d88b02245742347c94f1e108c534dda442188015ff80669b3"
|
||||
digest = "1:a623ed4965cad144a32551cb009b9bad9ad247c22ca1afdd934fc85d0c891f93"
|
||||
name = "google.golang.org/appengine"
|
||||
packages = ["cloudsql"]
|
||||
packages = [
|
||||
"cloudsql",
|
||||
"internal",
|
||||
"internal/base",
|
||||
"internal/datastore",
|
||||
"internal/log",
|
||||
"internal/remote_api",
|
||||
"internal/urlfetch",
|
||||
"urlfetch",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "ae0ab99deb4dc413a2b4bd6c8bdd0eb67f1e4d06"
|
||||
version = "v1.2.0"
|
||||
revision = "4a4468ece617fc8205e99368fa2200e9d1fad421"
|
||||
version = "v1.3.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@@ -1005,10 +1076,10 @@
|
||||
name = "google.golang.org/genproto"
|
||||
packages = ["googleapis/rpc/status"]
|
||||
pruneopts = "UT"
|
||||
revision = "0e822944c569bf5c9afd034adaa56208bd2906ac"
|
||||
revision = "b5d43981345bdb2c233eb4bf3277847b48c6fdc6"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:ab8e92d746fb5c4c18846b0879842ac8e53b3d352449423d0924a11f1020ae1b"
|
||||
digest = "1:c3ad9841823db6da420a5625b367913b4ff54bbe60e8e3c98bd20e243e62e2d2"
|
||||
name = "google.golang.org/grpc"
|
||||
packages = [
|
||||
".",
|
||||
@@ -1039,8 +1110,8 @@
|
||||
"tap",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "8dea3dc473e90c8179e519d91302d0597c0ca1d1"
|
||||
version = "v1.15.0"
|
||||
revision = "2e463a05d100327ca47ac218281906921038fd95"
|
||||
version = "v1.16.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:2655728699af00d823b0a68bd7169fd241a30c04252f456b34421908701b9c3f"
|
||||
@@ -1051,20 +1122,20 @@
|
||||
version = "v1.2"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:cbc72c4c4886a918d6ab4b95e347ffe259846260f99ebdd8a198c2331cf2b2e9"
|
||||
digest = "1:1b4724d3c8125f6044925f02b485b74bfec9905cbf579d95aafd1a6c8f8447d3"
|
||||
name = "gopkg.in/go-playground/validator.v8"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "5f1438d3fca68893a817e4a66806cea46a9e4ebf"
|
||||
version = "v8.18.2"
|
||||
revision = "5f57d2222ad794d0dffb07e664ea05e2ee07d60c"
|
||||
version = "v8.18.1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:2d1fbdc6777e5408cabeb02bf336305e724b925ff4546ded0fa8715a7267922a"
|
||||
digest = "1:ef72505cf098abdd34efeea032103377bec06abb61d8a06f002d5d296a4b1185"
|
||||
name = "gopkg.in/inf.v0"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "d2d2541c53f18d2a059457998ce2876cc8e67cbf"
|
||||
version = "v0.9.1"
|
||||
revision = "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4"
|
||||
version = "v0.9.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:342378ac4dcb378a5448dd723f0784ae519383532f5e70ade24132c4c8693202"
|
||||
@@ -1075,7 +1146,7 @@
|
||||
version = "v2.2.1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:74142cd2275f77547c35ac51514108d9798a09aa0cf377a5c1084718ef7aa225"
|
||||
digest = "1:910ec974550174f4ca48b9f4a3caec16b693e584c3762dc726dc0dcf28f8e318"
|
||||
name = "k8s.io/api"
|
||||
packages = [
|
||||
"admissionregistration/v1alpha1",
|
||||
@@ -1089,10 +1160,12 @@
|
||||
"authorization/v1beta1",
|
||||
"autoscaling/v1",
|
||||
"autoscaling/v2beta1",
|
||||
"autoscaling/v2beta2",
|
||||
"batch/v1",
|
||||
"batch/v1beta1",
|
||||
"batch/v2alpha1",
|
||||
"certificates/v1beta1",
|
||||
"coordination/v1beta1",
|
||||
"core/v1",
|
||||
"events/v1beta1",
|
||||
"extensions/v1beta1",
|
||||
@@ -1109,10 +1182,12 @@
|
||||
"storage/v1beta1",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "072894a440bdee3a891dea811fe42902311cd2a3"
|
||||
revision = "fd83cbc87e7632ccd8bbab63d2b673d4e0c631cc"
|
||||
version = "kubernetes-1.12.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:29d5abc33d8cbec19b4cd032a87d28010dd615578dd695a655fc3d5ec3ab86b6"
|
||||
branch = "master"
|
||||
digest = "1:8d1aedc658be5554671b9fa17e03beba96481e9a9b445baa4756836a65ed342c"
|
||||
name = "k8s.io/apimachinery"
|
||||
packages = [
|
||||
"pkg/api/errors",
|
||||
@@ -1140,22 +1215,22 @@
|
||||
"pkg/util/framer",
|
||||
"pkg/util/intstr",
|
||||
"pkg/util/json",
|
||||
"pkg/util/naming",
|
||||
"pkg/util/net",
|
||||
"pkg/util/runtime",
|
||||
"pkg/util/sets",
|
||||
"pkg/util/validation",
|
||||
"pkg/util/validation/field",
|
||||
"pkg/util/wait",
|
||||
"pkg/util/yaml",
|
||||
"pkg/version",
|
||||
"pkg/watch",
|
||||
"third_party/forked/golang/reflect",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "103fd098999dc9c0c88536f5c9ad2e5da39373ae"
|
||||
revision = "90473842928c717082a393d6adceee99889fe8cc"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:ac46cc5d5c55dd93d4844327334d2253d563d76f14d4b38a8b522b97f0f52214"
|
||||
digest = "1:51fd9ac9f2be10d79f5af101a7a1d758ef283fdb028a0d11198754bd3d4a6020"
|
||||
name = "k8s.io/client-go"
|
||||
packages = [
|
||||
"discovery",
|
||||
@@ -1172,10 +1247,12 @@
|
||||
"kubernetes/typed/authorization/v1beta1",
|
||||
"kubernetes/typed/autoscaling/v1",
|
||||
"kubernetes/typed/autoscaling/v2beta1",
|
||||
"kubernetes/typed/autoscaling/v2beta2",
|
||||
"kubernetes/typed/batch/v1",
|
||||
"kubernetes/typed/batch/v1beta1",
|
||||
"kubernetes/typed/batch/v2alpha1",
|
||||
"kubernetes/typed/certificates/v1beta1",
|
||||
"kubernetes/typed/coordination/v1beta1",
|
||||
"kubernetes/typed/core/v1",
|
||||
"kubernetes/typed/events/v1beta1",
|
||||
"kubernetes/typed/extensions/v1beta1",
|
||||
@@ -1212,8 +1289,16 @@
|
||||
"util/integer",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "7d04d0e2a0a1a4d4a1cd6baa432a2301492e4e65"
|
||||
version = "v8.0.0"
|
||||
revision = "1638f8970cefaa404ff3a62950f88b08292b2696"
|
||||
version = "v9.0.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:7719608fe0b52a4ece56c2dde37bedd95b938677d1ab0f84b8a7852e4c59f849"
|
||||
name = "sigs.k8s.io/yaml"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "fd68e9863619f6ec2fdd8625fe1f02e7c877e480"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:356a33d2d627cbb232a1d71cc42051fbac0e5e6a1717679f110054baa02472e5"
|
||||
@@ -1318,6 +1403,12 @@
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests",
|
||||
"github.com/aliyun/aliyun-oss-go-sdk/oss",
|
||||
"github.com/aokoli/goutils",
|
||||
"github.com/aws/aws-sdk-go/aws",
|
||||
"github.com/aws/aws-sdk-go/aws/credentials",
|
||||
"github.com/aws/aws-sdk-go/aws/session",
|
||||
"github.com/aws/aws-sdk-go/service/ec2",
|
||||
"github.com/aws/aws-sdk-go/service/iam",
|
||||
"github.com/aws/aws-sdk-go/service/s3",
|
||||
"github.com/bitly/go-simplejson",
|
||||
"github.com/c-bata/go-prompt",
|
||||
"github.com/coredns/coredns/core/dnsserver",
|
||||
@@ -1359,8 +1450,12 @@
|
||||
"github.com/mholt/caddy/startupshutdown",
|
||||
"github.com/miekg/dns",
|
||||
"github.com/moul/http2curl",
|
||||
"github.com/nelsonken/cos-go-sdk-v5/cos",
|
||||
"github.com/serialx/hashring",
|
||||
"github.com/stretchr/testify/assert",
|
||||
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common",
|
||||
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/http",
|
||||
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile",
|
||||
"github.com/tredoe/osutil/user/crypt/sha512_crypt",
|
||||
"github.com/vmware/govmomi",
|
||||
"github.com/vmware/govmomi/object",
|
||||
|
||||
+135
-80
@@ -25,17 +25,145 @@
|
||||
# unused-packages = true
|
||||
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/360EntSecGroup-Skylar/excelize"
|
||||
version = "1.4.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/Azure/azure-sdk-for-go"
|
||||
version = "=19.1.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/Microsoft/azure-vhd-utils"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/aliyun/alibaba-cloud-sdk-go"
|
||||
version = "0.7.4"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/aliyun/aliyun-oss-go-sdk"
|
||||
version = "1.9.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/aokoli/goutils"
|
||||
version = "1.0.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/aws/aws-sdk-go"
|
||||
version = "=1.15.73"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/bitly/go-simplejson"
|
||||
version = "0.5.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/c-bata/go-prompt"
|
||||
version = "=0.2.1"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "yunion.io/x/jsonutils"
|
||||
name = "github.com/coredns/coredns"
|
||||
version = "1.2.6"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/fatih/color"
|
||||
version = "1.7.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/go-sql-driver/mysql"
|
||||
version = "1.4.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/golang-plus/uuid"
|
||||
version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "yunion.io/x/sqlchemy"
|
||||
name = "github.com/googollee/go-socket.io"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/gorilla/mux"
|
||||
version = "1.6.2"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/gorilla/websocket"
|
||||
version = "1.4.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/gosuri/uitable"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/hako/durafmt"
|
||||
version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/jinzhu/gorm"
|
||||
version = "1.9.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/kr/pty"
|
||||
version = "1.1.3"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/mholt/caddy"
|
||||
version = "0.10.11"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/miekg/dns"
|
||||
version = "1.0.15"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/moul/http2curl"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/nelsonken/cos-go-sdk-v5"
|
||||
version = "1.21.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/serialx/hashring"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/stretchr/testify"
|
||||
version = "1.2.2"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/tencentcloud/tencentcloud-sdk-go"
|
||||
version = "=3.0.30"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/tredoe/osutil"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/vmware/govmomi"
|
||||
version = "0.19.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
|
||||
[[constraint]]
|
||||
name = "gopkg.in/gin-gonic/gin.v1"
|
||||
version = "1.2.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "k8s.io/api"
|
||||
version = "kubernetes-1.12.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "k8s.io/apimachinery"
|
||||
|
||||
[[constraint]]
|
||||
name = "k8s.io/client-go"
|
||||
version = "9.0.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "yunion.io/x/jsonutils"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
@@ -45,87 +173,14 @@
|
||||
branch = "master"
|
||||
name = "yunion.io/x/pkg"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "yunion.io/x/sqlchemy"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "yunion.io/x/structarg"
|
||||
|
||||
# client-go v8.0.0 uses apimachinery 103fd098999dc9c0c88536f5c9ad2e5da39373ae
|
||||
# and api 072894a440bdee3a891dea811fe42902311cd2a3 (see Godep.json). go dep
|
||||
# is unable to match Godep.json automatically so have to specify here.
|
||||
[[constraint]]
|
||||
name = "k8s.io/client-go"
|
||||
version = "v8.0.0"
|
||||
[[override]]
|
||||
name = "k8s.io/apimachinery"
|
||||
revision = "103fd098999dc9c0c88536f5c9ad2e5da39373ae"
|
||||
[[override]]
|
||||
name = "k8s.io/api"
|
||||
revision = "072894a440bdee3a891dea811fe42902311cd2a3"
|
||||
|
||||
[[override]]
|
||||
name = "github.com/apache/thrift"
|
||||
revision = "e59b73d3c2bf1c328ccb78e683c0462fa1a473c7"
|
||||
[[override]]
|
||||
name = "github.com/ugorji/go"
|
||||
revision = "f3cacc17c85ecb7f1b6a9e373ee85d1480919868"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/coredns/coredns"
|
||||
version = "v1.2.0"
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/vmware/govmomi"
|
||||
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/hako/durafmt"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/Azure/azure-sdk-for-go"
|
||||
version = "19.1.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/googollee/go-socket.io"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/kr/pty"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/Microsoft/azure-vhd-utils"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/texttheater/golang-levenshtein"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/360EntSecGroup-Skylar/excelize"
|
||||
version = "v1.3.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/tencentcloud/tencentcloud-sdk-go"
|
||||
version = "=v3.0.28"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/nelsonken/cos-go-sdk-v5"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/tredoe/osutil"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/forhappy/cos-go-sdk"
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/util/aws"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
"yunion.io/x/structarg"
|
||||
|
||||
_ "yunion.io/x/onecloud/pkg/util/aws/shell"
|
||||
)
|
||||
|
||||
type BaseOptions struct {
|
||||
Help bool `help:"Show help"`
|
||||
AccessUrl string `help:"Access key" default:"$AWS_ACCESS_URL" choices:"ChinaCloud|InternationalCloud"`
|
||||
AccessKey string `help:"Access key" default:"$AWS_ACCESS_KEY"`
|
||||
Secret string `help:"Secret" default:"$AWS_SECRET"`
|
||||
RegionId string `help:"RegionId" default:"$AWS_REGION"`
|
||||
SUBCOMMAND string `help:"awscli subcommand" subcommand:"true"`
|
||||
}
|
||||
|
||||
func getSubcommandParser() (*structarg.ArgumentParser, error) {
|
||||
parse, e := structarg.NewArgumentParser(&BaseOptions{},
|
||||
"awscli",
|
||||
"Command-line interface to aws API.",
|
||||
`See "awscli help COMMAND" for help on a specific command.`)
|
||||
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
|
||||
subcmd := parse.GetSubcommand()
|
||||
if subcmd == nil {
|
||||
return nil, fmt.Errorf("No subcommand argument.")
|
||||
}
|
||||
type HelpOptions struct {
|
||||
SUBCOMMAND string `help:"sub-command name"`
|
||||
}
|
||||
shellutils.R(&HelpOptions{}, "help", "Show help of a subcommand", func(args *HelpOptions) error {
|
||||
helpstr, e := subcmd.SubHelpString(args.SUBCOMMAND)
|
||||
if e != nil {
|
||||
return e
|
||||
} else {
|
||||
fmt.Print(helpstr)
|
||||
return nil
|
||||
}
|
||||
})
|
||||
for _, v := range shellutils.CommandTable {
|
||||
_, e := subcmd.AddSubParser(v.Options, v.Command, v.Desc, v.Callback)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
}
|
||||
return parse, nil
|
||||
}
|
||||
|
||||
func showErrorAndExit(e error) {
|
||||
log.Errorf("%s", e)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func newClient(options *BaseOptions) (*aws.SRegion, error) {
|
||||
if len(options.AccessKey) == 0 {
|
||||
return nil, fmt.Errorf("Missing accessKey")
|
||||
}
|
||||
|
||||
if len(options.Secret) == 0 {
|
||||
return nil, fmt.Errorf("Missing secret")
|
||||
}
|
||||
|
||||
cli, err := aws.NewAwsClient("", "", options.AccessUrl, options.AccessKey, options.Secret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
region := cli.GetRegion(options.RegionId)
|
||||
if region == nil {
|
||||
return nil, fmt.Errorf("No such region %s", options.RegionId)
|
||||
}
|
||||
|
||||
return region, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
parser, e := getSubcommandParser()
|
||||
if e != nil {
|
||||
showErrorAndExit(e)
|
||||
}
|
||||
e = parser.ParseArgs(os.Args[1:], false)
|
||||
options := parser.Options().(*BaseOptions)
|
||||
|
||||
if options.Help {
|
||||
fmt.Print(parser.HelpString())
|
||||
} else {
|
||||
subcmd := parser.GetSubcommand()
|
||||
subparser := subcmd.GetSubParser()
|
||||
if e != nil {
|
||||
if subparser != nil {
|
||||
fmt.Print(subparser.Usage())
|
||||
} else {
|
||||
fmt.Print(parser.Usage())
|
||||
}
|
||||
showErrorAndExit(e)
|
||||
} else {
|
||||
suboptions := subparser.Options()
|
||||
if options.SUBCOMMAND == "help" {
|
||||
e = subcmd.Invoke(suboptions)
|
||||
} else {
|
||||
var region *aws.SRegion
|
||||
region, e = newClient(options)
|
||||
if e != nil {
|
||||
showErrorAndExit(e)
|
||||
}
|
||||
e = subcmd.Invoke(region, suboptions)
|
||||
}
|
||||
if e != nil {
|
||||
showErrorAndExit(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,334 @@
|
||||
package guestdrivers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
type SAwsGuestDriver struct {
|
||||
SManagedVirtualizedGuestDriver
|
||||
}
|
||||
|
||||
func (self *SAwsGuestDriver) GetHypervisor() string {
|
||||
return models.HYPERVISOR_AWS
|
||||
}
|
||||
|
||||
func (self *SAwsGuestDriver) ChooseHostStorage(host *models.SHost, backend string) *models.SStorage {
|
||||
storages := host.GetAttachedStorages("")
|
||||
for i := 0; i < len(storages); i += 1 {
|
||||
if storages[i].StorageType == backend {
|
||||
return &storages[i]
|
||||
}
|
||||
}
|
||||
|
||||
for _, stype := range []string{"gp2", "io1", "st1", "sc1", "standard"} {
|
||||
for i := 0; i < len(storages); i += 1 {
|
||||
if storages[i].StorageType == stype {
|
||||
return &storages[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAwsGuestDriver) GetDetachDiskStatus() ([]string, error) {
|
||||
return []string{models.VM_READY, models.VM_RUNNING}, nil
|
||||
}
|
||||
|
||||
func (self *SAwsGuestDriver) RequestDetachDisk(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
|
||||
return guest.StartSyncTask(ctx, task.GetUserCred(), false, task.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *SAwsGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
return self.SManagedVirtualizedGuestDriver.ValidateCreateData(ctx, userCred, data)
|
||||
}
|
||||
|
||||
func fetchAwsIVMinfo(desc SManagedVMCreateConfig, iVM cloudprovider.ICloudVM, guestId string) *jsonutils.JSONDict {
|
||||
data := jsonutils.NewDict()
|
||||
data.Add(jsonutils.NewString(iVM.GetOSType()), "os")
|
||||
if len(desc.OsDistribution) > 0 {
|
||||
data.Add(jsonutils.NewString(desc.OsDistribution), "distro")
|
||||
}
|
||||
if len(desc.OsVersion) > 0 {
|
||||
data.Add(jsonutils.NewString(desc.OsVersion), "version")
|
||||
}
|
||||
|
||||
idisks, err := iVM.GetIDisks()
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("GetiDisks error %s", err)
|
||||
} else {
|
||||
diskInfo := make([]SDiskInfo, len(idisks))
|
||||
for i := 0; i < len(idisks); i += 1 {
|
||||
dinfo := SDiskInfo{}
|
||||
dinfo.Uuid = idisks[i].GetGlobalId()
|
||||
dinfo.Size = idisks[i].GetDiskSizeMB()
|
||||
dinfo.DiskType = idisks[i].GetDiskType()
|
||||
if metaData := idisks[i].GetMetadata(); metaData != nil {
|
||||
dinfo.Metadata = make(map[string]string, 0)
|
||||
if err := metaData.Unmarshal(dinfo.Metadata); err != nil {
|
||||
log.Errorf("Get disk %s metadata info error: %v", idisks[i].GetName(), err)
|
||||
}
|
||||
}
|
||||
diskInfo[i] = dinfo
|
||||
}
|
||||
data.Add(jsonutils.Marshal(&diskInfo), "disks")
|
||||
}
|
||||
|
||||
data.Add(jsonutils.NewString(iVM.GetGlobalId()), "uuid")
|
||||
data.Add(iVM.GetMetadata(), "metadata")
|
||||
return data
|
||||
}
|
||||
|
||||
func (self *SAwsGuestDriver) RequestDeployGuestOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, task taskman.ITask) error {
|
||||
config := guest.GetDeployConfigOnHost(ctx, host, task.GetParams())
|
||||
log.Debugf("RequestDeployGuestOnHost: %s", config)
|
||||
|
||||
action, err := config.GetString("action")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ihost, err := host.GetIHost()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
desc := SManagedVMCreateConfig{}
|
||||
err = config.Unmarshal(&desc, "desc")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
publicKey, _ := config.GetString("public_key")
|
||||
passwd, _ := config.GetString("password")
|
||||
|
||||
adminPublicKey, _ := config.GetString("admin_public_key")
|
||||
projectPublicKey, _ := config.GetString("project_public_key")
|
||||
oUserData, _ := config.GetString("user_data")
|
||||
|
||||
userData := generateUserData(adminPublicKey, projectPublicKey, oUserData)
|
||||
|
||||
switch action {
|
||||
case "create":
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
nets := guest.GetNetworks()
|
||||
net := nets[0].GetNetwork()
|
||||
vpc := net.GetVpc()
|
||||
|
||||
ivpc, err := vpc.GetIVpc()
|
||||
if err != nil {
|
||||
log.Errorf("getIVPC fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
secgrpId, err := ivpc.SyncSecurityGroup(desc.SecGroupId, desc.SecGroupName, desc.SecRules)
|
||||
if err != nil {
|
||||
log.Errorf("SyncSecurityGroup fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
iVM, err := ihost.CreateVM(desc.Name, desc.ExternalImageId, desc.SysDiskSize, desc.Cpu, desc.Memory, desc.ExternalNetworkId,
|
||||
desc.IpAddr, desc.Description, "", desc.StorageType, desc.DataDisks, publicKey, secgrpId, userData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Debugf("VMcreated %s, wait status running ...", iVM.GetGlobalId())
|
||||
err = cloudprovider.WaitStatus(iVM, models.VM_RUNNING, time.Second*5, time.Second*1800)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Debugf("VMcreated %s, and status is ready", iVM.GetGlobalId())
|
||||
|
||||
iVM, err = ihost.GetIVMById(iVM.GetGlobalId())
|
||||
if err != nil {
|
||||
log.Errorf("cannot find vm %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := fetchAwsIVMinfo(desc, iVM, guest.Id)
|
||||
return data, nil
|
||||
})
|
||||
case "deploy":
|
||||
iVM, err := ihost.GetIVMById(guest.GetExternalId())
|
||||
if err != nil || iVM == nil {
|
||||
log.Errorf("cannot find vm %s", err)
|
||||
return fmt.Errorf("cannot find vm")
|
||||
}
|
||||
|
||||
params := task.GetParams()
|
||||
log.Debugf("Deploy VM params %s", params.String())
|
||||
|
||||
name, _ := params.GetString("name")
|
||||
description, _ := params.GetString("description")
|
||||
publicKey, _ := config.GetString("public_key")
|
||||
deleteKeypair := jsonutils.QueryBoolean(params, "__delete_keypair__", false)
|
||||
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
err := iVM.DeployVM(name, passwd, publicKey, deleteKeypair, description)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := fetchIVMinfo(desc, iVM, guest.Id, DEFAULT_USER, passwd, action)
|
||||
return data, nil
|
||||
})
|
||||
case "rebuild":
|
||||
iVM, err := ihost.GetIVMById(guest.GetExternalId())
|
||||
if err != nil || iVM == nil {
|
||||
log.Errorf("cannot find vm %s", err)
|
||||
return fmt.Errorf("cannot find vm")
|
||||
}
|
||||
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
diskId, err := iVM.RebuildRoot(desc.ExternalImageId, passwd, publicKey, desc.SysDiskSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Debugf("VMrebuildRoot %s new diskID %s, wait status ready ...", iVM.GetGlobalId(), diskId)
|
||||
|
||||
err = cloudprovider.WaitStatus(iVM, models.VM_READY, time.Second*5, time.Second*1800)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Debugf("VMrebuildRoot %s, and status is ready", iVM.GetGlobalId())
|
||||
|
||||
maxWaitSecs := 300
|
||||
waited := 0
|
||||
|
||||
for {
|
||||
// hack, wait disk number consistent
|
||||
idisks, err := iVM.GetIDisks()
|
||||
if err != nil {
|
||||
log.Errorf("fail to find VM idisks %s", err)
|
||||
return nil, err
|
||||
}
|
||||
if len(idisks) < len(desc.DataDisks)+1 {
|
||||
if waited > maxWaitSecs {
|
||||
log.Errorf("inconsistent disk number, wait timeout, must be something wrong on remote")
|
||||
return nil, cloudprovider.ErrTimeout
|
||||
}
|
||||
log.Debugf("inconsistent disk number???? %d != %d", len(idisks), len(desc.DataDisks)+1)
|
||||
time.Sleep(time.Second * 5)
|
||||
waited += 5
|
||||
} else {
|
||||
if idisks[0].GetGlobalId() != diskId {
|
||||
log.Errorf("system disk id inconsistent %s != %s", idisks[0].GetGlobalId(), diskId)
|
||||
return nil, fmt.Errorf("inconsistent sys disk id after rebuild root")
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
data := fetchIVMinfo(desc, iVM, guest.Id, DEFAULT_USER, passwd, action)
|
||||
|
||||
return data, nil
|
||||
})
|
||||
default:
|
||||
log.Errorf("RequestDeployGuestOnHost: Action %s not supported", action)
|
||||
return fmt.Errorf("Action %s not supported", action)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAwsGuestDriver) OnGuestDeployTaskDataReceived(ctx context.Context, guest *models.SGuest, task taskman.ITask, data jsonutils.JSONObject) error {
|
||||
if data.Contains("disks") {
|
||||
diskInfo := make([]SDiskInfo, 0)
|
||||
err := data.Unmarshal(&diskInfo, "disks")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
disks := guest.GetDisks()
|
||||
if len(disks) != len(diskInfo) {
|
||||
msg := fmt.Sprintf("inconsistent disk number: have %d want %d", len(disks), len(diskInfo))
|
||||
log.Errorf(msg)
|
||||
return fmt.Errorf(msg)
|
||||
}
|
||||
for i := 0; i < len(diskInfo); i += 1 {
|
||||
disk := disks[i].GetDisk()
|
||||
_, err = disk.GetModelManager().TableSpec().Update(disk, func() error {
|
||||
disk.DiskSize = diskInfo[i].Size
|
||||
disk.ExternalId = diskInfo[i].Uuid
|
||||
disk.DiskType = diskInfo[i].DiskType
|
||||
disk.Status = models.DISK_READY
|
||||
if len(diskInfo[i].Metadata) > 0 {
|
||||
for key, value := range diskInfo[i].Metadata {
|
||||
if err := disk.SetMetadata(ctx, key, value, task.GetUserCred()); err != nil {
|
||||
log.Errorf("set disk %s mata %s => %s error: %v", disk.Name, key, value, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("save disk info failed %s", err)
|
||||
log.Errorf(msg)
|
||||
break
|
||||
} else {
|
||||
db.OpsLog.LogEvent(disk, db.ACT_ALLOCATE, disk.GetShortDesc(), task.GetUserCred())
|
||||
}
|
||||
}
|
||||
}
|
||||
uuid, _ := data.GetString("uuid")
|
||||
if len(uuid) > 0 {
|
||||
guest.SetExternalId(uuid)
|
||||
}
|
||||
|
||||
if metaData, _ := data.Get("metadata"); metaData != nil {
|
||||
meta := make(map[string]string, 0)
|
||||
if err := metaData.Unmarshal(meta); err != nil {
|
||||
log.Errorf("Get guest %s metadata error: %v", guest.Name, err)
|
||||
} else {
|
||||
for key, value := range meta {
|
||||
if err := guest.SetMetadata(ctx, key, value, task.GetUserCred()); err != nil {
|
||||
log.Errorf("set guest %s mata %s => %s error: %v", guest.Name, key, value, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
guest.SaveDeployInfo(ctx, task.GetUserCred(), data)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAwsGuestDriver) RequestDiskSnapshot(ctx context.Context, guest *models.SGuest, task taskman.ITask, snapshotId, diskId string) error {
|
||||
iDisk, _ := models.DiskManager.FetchById(diskId)
|
||||
disk := iDisk.(*models.SDisk)
|
||||
providerDisk, err := disk.GetIDisk()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
iSnapshot, _ := models.SnapshotManager.FetchById(snapshotId)
|
||||
snapshot := iSnapshot.(*models.SSnapshot)
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
cloudSnapshot, err := providerDisk.CreateISnapshot(snapshot.Name, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res := jsonutils.NewDict()
|
||||
res.Set("snapshot_id", jsonutils.NewString(cloudSnapshot.GetId()))
|
||||
res.Set("manager_id", jsonutils.NewString(cloudSnapshot.GetManagerId()))
|
||||
res.Set("cloudregion_id", jsonutils.NewString(cloudSnapshot.GetRegionId()))
|
||||
return res, nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAwsGuestDriver) GetAttachDiskStatus() ([]string, error) {
|
||||
return []string{models.VM_READY, models.VM_RUNNING}, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
driver := SAwsGuestDriver{}
|
||||
models.RegisterGuestDriver(&driver)
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
package hostdrivers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
type SAwsHostDriver struct {
|
||||
SBaseHostDriver
|
||||
}
|
||||
|
||||
func (self *SAwsHostDriver) GetHostType() string {
|
||||
return models.HOST_TYPE_AWS
|
||||
}
|
||||
|
||||
func (self *SAwsHostDriver) CheckAndSetCacheImage(ctx context.Context, host *models.SHost, storageCache *models.SStoragecache, task taskman.ITask) error {
|
||||
params := task.GetParams()
|
||||
imageId, err := params.GetString("image_id")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
osArch, _ := params.GetString("os_arch")
|
||||
osType, _ := params.GetString("os_type")
|
||||
osDist, _ := params.GetString("os_distribution")
|
||||
|
||||
isForce := jsonutils.QueryBoolean(params, "is_force", false)
|
||||
userCred := task.GetUserCred()
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
|
||||
lockman.LockRawObject(ctx, "cachedimages", fmt.Sprintf("%s-%s", storageCache.Id, imageId))
|
||||
defer lockman.ReleaseRawObject(ctx, "cachedimages", fmt.Sprintf("%s-%s", storageCache.Id, imageId))
|
||||
|
||||
scimg := models.StoragecachedimageManager.Register(ctx, task.GetUserCred(), storageCache.Id, imageId)
|
||||
|
||||
iStorageCache, err := storageCache.GetIStorageCache()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
extImgId, err := iStorageCache.UploadImage(userCred, imageId, osArch, osType, osDist, scimg.ExternalId, isForce)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
scimg.SetExternalId(extImgId)
|
||||
|
||||
ret := jsonutils.NewDict()
|
||||
ret.Add(jsonutils.NewString(extImgId), "image_id")
|
||||
return ret, nil
|
||||
}
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAwsHostDriver) RequestPrepareSaveDiskOnHost(ctx context.Context, host *models.SHost, disk *models.SDisk, imageId string, task taskman.ITask) error {
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAwsHostDriver) RequestSaveUploadImageOnHost(ctx context.Context, host *models.SHost, disk *models.SDisk, imageId string, task taskman.ITask, data jsonutils.JSONObject) error {
|
||||
if iDisk, err := disk.GetIDisk(); err != nil {
|
||||
return err
|
||||
} else if iStorage, err := disk.GetIStorage(); err != nil {
|
||||
return err
|
||||
} else if iStoragecache := iStorage.GetIStoragecache(); iStoragecache == nil {
|
||||
return httperrors.NewResourceNotFoundError("fail to find iStoragecache for storage: %s", iStorage.GetName())
|
||||
} else {
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
if snapshot, err := iDisk.CreateISnapshot(fmt.Sprintf("Snapshot-%s", imageId), "PrepareSaveImage"); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
params := task.GetParams()
|
||||
osType, _ := params.GetString("properties", "os_type")
|
||||
|
||||
scimg := models.StoragecachedimageManager.Register(ctx, task.GetUserCred(), iStoragecache.GetId(), imageId)
|
||||
if scimg.Status != models.CACHED_IMAGE_STATUS_READY {
|
||||
scimg.SetStatus(task.GetUserCred(), models.CACHED_IMAGE_STATUS_CACHING, "request_prepare_save_disk_on_host")
|
||||
}
|
||||
if iImage, err := iStoragecache.CreateIImage(snapshot.GetId(), fmt.Sprintf("Image-%s", imageId), osType, ""); err != nil {
|
||||
log.Errorf("fail to create iImage: %v", err)
|
||||
scimg.SetStatus(task.GetUserCred(), models.CACHED_IMAGE_STATUS_CACHE_FAILED, err.Error())
|
||||
return nil, err
|
||||
} else {
|
||||
scimg.SetExternalId(iImage.GetId())
|
||||
if result, err := iStoragecache.DownloadImage(task.GetUserCred(), imageId, iImage.GetId(), options.Options.TempPath); err != nil {
|
||||
scimg.SetStatus(task.GetUserCred(), models.CACHED_IMAGE_STATUS_CACHE_FAILED, err.Error())
|
||||
return nil, err
|
||||
} else {
|
||||
if err := iImage.Delete(); err != nil {
|
||||
log.Errorf("Delete iImage %s failed: %v", iImage.GetId(), err)
|
||||
}
|
||||
if err := snapshot.Delete(); err != nil {
|
||||
log.Errorf("Delete snapshot %s failed: %v", snapshot.GetId(), err)
|
||||
}
|
||||
scimg.SetStatus(task.GetUserCred(), models.CACHED_IMAGE_STATUS_READY, "")
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAwsHostDriver) RequestAllocateDiskOnStorage(ctx context.Context, host *models.SHost, storage *models.SStorage, disk *models.SDisk, task taskman.ITask, content *jsonutils.JSONDict) error {
|
||||
if iCloudStorage, err := storage.GetIStorage(); err != nil {
|
||||
return err
|
||||
} else {
|
||||
if size, err := content.Int("size"); err != nil {
|
||||
return err
|
||||
} else {
|
||||
size = size >> 10
|
||||
if iDisk, err := iCloudStorage.CreateIDisk(disk.GetName(), int(size), ""); err != nil {
|
||||
return err
|
||||
} else {
|
||||
if _, err := disk.GetModelManager().TableSpec().Update(disk, func() error {
|
||||
disk.ExternalId = iDisk.GetGlobalId()
|
||||
|
||||
if metaData := iDisk.GetMetadata(); metaData != nil {
|
||||
meta := make(map[string]string)
|
||||
if err := metaData.Unmarshal(meta); err != nil {
|
||||
log.Errorf("Get disk %s Metadata error: %v", disk.Name, err)
|
||||
} else {
|
||||
for key, value := range meta {
|
||||
if err := disk.SetMetadata(ctx, key, value, task.GetUserCred()); err != nil {
|
||||
log.Errorf("set disk %s mata %s => %s error: %v", disk.Name, key, value, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
log.Errorf("Update disk externalId err: %v", err)
|
||||
return err
|
||||
}
|
||||
data := jsonutils.NewDict()
|
||||
data.Add(jsonutils.NewInt(int64(iDisk.GetDiskSizeMB())), "disk_size")
|
||||
data.Add(jsonutils.NewString(iDisk.GetDiskFormat()), "disk_format")
|
||||
task.ScheduleRun(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAwsHostDriver) RequestDeallocateDiskOnHost(host *models.SHost, storage *models.SStorage, disk *models.SDisk, task taskman.ITask) error {
|
||||
data := jsonutils.NewDict()
|
||||
if iCloudStorage, err := storage.GetIStorage(); err != nil {
|
||||
return err
|
||||
} else if iDisk, err := iCloudStorage.GetIDisk(disk.GetExternalId()); err != nil {
|
||||
if err == cloudprovider.ErrNotFound {
|
||||
task.ScheduleRun(data)
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
} else if err := iDisk.Delete(); err != nil {
|
||||
return err
|
||||
}
|
||||
task.ScheduleRun(data)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAwsHostDriver) RequestResizeDiskOnHostOnline(host *models.SHost, storage *models.SStorage, disk *models.SDisk, size int64, task taskman.ITask) error {
|
||||
return self.RequestResizeDiskOnHost(host, storage, disk, size, task)
|
||||
}
|
||||
|
||||
func (self *SAwsHostDriver) RequestResizeDiskOnHost(host *models.SHost, storage *models.SStorage, disk *models.SDisk, size int64, task taskman.ITask) error {
|
||||
if iCloudStorage, err := storage.GetIStorage(); err != nil {
|
||||
return err
|
||||
} else if iDisk, err := iCloudStorage.GetIDisk(disk.GetExternalId()); err != nil {
|
||||
return err
|
||||
} else if err := iDisk.Resize(size >> 10); err != nil {
|
||||
return err
|
||||
} else {
|
||||
task.ScheduleRun(jsonutils.Marshal(map[string]int64{"disk_size": size}))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
driver := SAwsHostDriver{}
|
||||
models.RegisterHostDriver(&driver)
|
||||
}
|
||||
@@ -33,6 +33,7 @@ const (
|
||||
CLOUD_PROVIDER_ALIYUN = "Aliyun"
|
||||
CLOUD_PROVIDER_QCLOUD = "Qcloud"
|
||||
CLOUD_PROVIDER_AZURE = "Azure"
|
||||
CLOUD_PROVIDER_AWS = "Aws"
|
||||
)
|
||||
|
||||
type SCloudproviderManager struct {
|
||||
|
||||
@@ -128,6 +128,7 @@ const (
|
||||
HYPERVISOR_ALIYUN = "aliyun"
|
||||
HYPERVISOR_QCLOUD = "qcloud"
|
||||
HYPERVISOR_AZURE = "azure"
|
||||
HYPERVISOR_AWS = "aws"
|
||||
|
||||
// HYPERVISOR_DEFAULT = HYPERVISOR_KVM
|
||||
HYPERVISOR_DEFAULT = HYPERVISOR_ALIYUN
|
||||
@@ -136,9 +137,9 @@ const (
|
||||
var VM_RUNNING_STATUS = []string{VM_START_START, VM_STARTING, VM_RUNNING, VM_SNAPSHOT_STREAM}
|
||||
var VM_CREATING_STATUS = []string{VM_CREATE_NETWORK, VM_CREATE_DISK, VM_START_DEPLOY, VM_DEPLOYING}
|
||||
|
||||
var HYPERVISORS = []string{HYPERVISOR_KVM, HYPERVISOR_BAREMETAL, HYPERVISOR_ESXI, HYPERVISOR_CONTAINER, HYPERVISOR_ALIYUN, HYPERVISOR_AZURE, HYPERVISOR_QCLOUD}
|
||||
var HYPERVISORS = []string{HYPERVISOR_KVM, HYPERVISOR_BAREMETAL, HYPERVISOR_ESXI, HYPERVISOR_CONTAINER, HYPERVISOR_ALIYUN, HYPERVISOR_AZURE, HYPERVISOR_AWS, HYPERVISOR_QCLOUD}
|
||||
|
||||
var PUBLIC_CLOUD_HYPERVISORS = []string{HYPERVISOR_ALIYUN, HYPERVISOR_AZURE}
|
||||
var PUBLIC_CLOUD_HYPERVISORS = []string{HYPERVISOR_ALIYUN, HYPERVISOR_AWS, HYPERVISOR_AZURE, HYPERVISOR_QCLOUD}
|
||||
|
||||
// var HYPERVISORS = []string{HYPERVISOR_ALIYUN}
|
||||
|
||||
@@ -149,6 +150,7 @@ var HYPERVISOR_HOSTTYPE = map[string]string{
|
||||
HYPERVISOR_CONTAINER: HOST_TYPE_KUBELET,
|
||||
HYPERVISOR_ALIYUN: HOST_TYPE_ALIYUN,
|
||||
HYPERVISOR_AZURE: HOST_TYPE_AZURE,
|
||||
HYPERVISOR_AWS: HOST_TYPE_AWS,
|
||||
HYPERVISOR_QCLOUD: HOST_TYPE_QCLOUD,
|
||||
}
|
||||
|
||||
@@ -159,6 +161,7 @@ var HOSTTYPE_HYPERVISOR = map[string]string{
|
||||
HOST_TYPE_KUBELET: HYPERVISOR_CONTAINER,
|
||||
HOST_TYPE_ALIYUN: HYPERVISOR_ALIYUN,
|
||||
HOST_TYPE_AZURE: HYPERVISOR_AZURE,
|
||||
HOST_TYPE_AWS: HYPERVISOR_AWS,
|
||||
HOST_TYPE_QCLOUD: HYPERVISOR_QCLOUD,
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ const (
|
||||
HOST_TYPE_HYPERV = "hyperv" // # Microsoft Hyper-V
|
||||
HOST_TYPE_XEN = "xen" // # XenServer
|
||||
HOST_TYPE_ALIYUN = "aliyun"
|
||||
HOST_TYPE_AWS = "aws"
|
||||
HOST_TYPE_QCLOUD = "qcloud"
|
||||
HOST_TYPE_AZURE = "azure"
|
||||
|
||||
@@ -82,7 +83,8 @@ const (
|
||||
HOST_STATUS_UNKNOWN = BAREMETAL_UNKNOWN
|
||||
)
|
||||
|
||||
var HOST_TYPES = []string{HOST_TYPE_BAREMETAL, HOST_TYPE_HYPERVISOR, HOST_TYPE_ESXI, HOST_TYPE_KUBELET, HOST_TYPE_XEN, HOST_TYPE_ALIYUN, HOST_TYPE_AZURE, HOST_TYPE_QCLOUD}
|
||||
var HOST_TYPES = []string{HOST_TYPE_BAREMETAL, HOST_TYPE_HYPERVISOR, HOST_TYPE_ESXI, HOST_TYPE_KUBELET, HOST_TYPE_XEN, HOST_TYPE_ALIYUN, HOST_TYPE_AZURE, HOST_TYPE_AWS, HOST_TYPE_QCLOUD}
|
||||
|
||||
var NIC_TYPES = []string{NIC_TYPE_IPMI, NIC_TYPE_ADMIN}
|
||||
|
||||
type SHostManager struct {
|
||||
|
||||
@@ -29,6 +29,11 @@ const (
|
||||
STORAGE_CLOUD_EFFICIENCY = "cloud_efficiency"
|
||||
STORAGE_CLOUD_SSD = "cloud_ssd"
|
||||
STORAGE_EPHEMERAL_SSD = "ephemeral_ssd"
|
||||
STORAGE_GP2_SSD = "gp2" // aws general purpose ssd
|
||||
STORAGE_IO1_SSD = "io1" // aws Provisioned IOPS SSD
|
||||
STORAGE_ST1_HDD = "st1" // aws Throughput Optimized HDD
|
||||
STORAGE_SC1_SSD = "sc1" // aws Cold HDD
|
||||
STORAGE_STANDARD_SSD = "standard" // aws Magnetic volumes
|
||||
|
||||
STORAGE_ENABLED = "enabled"
|
||||
STORAGE_DISABLED = "disabled"
|
||||
|
||||
@@ -58,6 +58,9 @@ type ComputeOptions struct {
|
||||
DefaultMaxSnapshotCount int `default:"9" help:"Per Disk max snapshot count, default 9"`
|
||||
DefaultMaxManualSnapshotCount int `default:"2" help:"Per Disk max manual snapshot count, default 2"`
|
||||
|
||||
// aws instance type file
|
||||
DefaultAwsInstanceTypeFile string `default:"/etc/yunion/aws_instance_types.json" help:"aws instance type json file"`
|
||||
|
||||
ConvertHypervisorDefaultTemplate string `default:"Default template" help:"Kvm baremetal convert option"`
|
||||
ConvertEsxiDefaultTemplate string `default:"Default template" help:"ESXI baremetal convert option"`
|
||||
ConvertKubeletDockerVolumeSize string `default:"256g" help:"Docker volume size"`
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
_ "yunion.io/x/onecloud/pkg/compute/hostdrivers"
|
||||
_ "yunion.io/x/onecloud/pkg/compute/tasks"
|
||||
_ "yunion.io/x/onecloud/pkg/util/aliyun/provider"
|
||||
_ "yunion.io/x/onecloud/pkg/util/aws/provider"
|
||||
_ "yunion.io/x/onecloud/pkg/util/azure/provider"
|
||||
_ "yunion.io/x/onecloud/pkg/util/esxi/provider"
|
||||
_ "yunion.io/x/onecloud/pkg/util/qcloud/provider"
|
||||
|
||||
@@ -18,6 +18,7 @@ const (
|
||||
HostHypervisorForKvm = "hypervisor"
|
||||
HostTypeAliyun = "aliyun"
|
||||
HostTypeAzure = "azure"
|
||||
HostTypeAws = "aws"
|
||||
HostTypeQcloud = "qcloud"
|
||||
HostTypeKubelet = "kubelet"
|
||||
|
||||
@@ -51,6 +52,7 @@ var (
|
||||
PublicCloudProviders = sets.NewString(
|
||||
HostTypeAliyun,
|
||||
HostTypeAzure,
|
||||
HostTypeAws,
|
||||
HostTypeQcloud,
|
||||
)
|
||||
|
||||
|
||||
@@ -150,6 +150,58 @@ func (self *SRegion) GetInstances(zoneId string, ids []string, offset int, limit
|
||||
return instances, int(total), nil
|
||||
}
|
||||
|
||||
func (self *SRegion) fetchTags(resourceType string, resourceId string) (*jsonutils.JSONDict, error) {
|
||||
// 资源类型。取值范围:
|
||||
// disk
|
||||
// instance
|
||||
// image
|
||||
// securitygroup
|
||||
// snapshot
|
||||
var page int64 = 1
|
||||
var pageSize int64 = 50
|
||||
params := make(map[string]string)
|
||||
params["RegionId"] = self.RegionId
|
||||
params["ResourceType"] = resourceType
|
||||
params["ResourceId"] = resourceId
|
||||
params["PageSize"] = fmt.Sprintf("%d", pageSize)
|
||||
params["PageNumber"] = fmt.Sprintf("%d", page)
|
||||
ret, err := self.ecsRequest("DescribeTags", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tags := jsonutils.NewDict()
|
||||
result, _ := ret.GetArray("Tags", "Tag")
|
||||
for _, item := range result {
|
||||
k, _ := item.GetString("TagKey")
|
||||
v, _ := item.Get("TagValue")
|
||||
if len(k) > 0 {
|
||||
tags.Set(k, v)
|
||||
}
|
||||
}
|
||||
|
||||
total, _ := ret.Int("TotalCount")
|
||||
for ; total > page*pageSize; page++ {
|
||||
params["PageSize"] = fmt.Sprintf("%d", pageSize)
|
||||
params["PageNumber"] = fmt.Sprintf("%d", page)
|
||||
ret, err := self.ecsRequest("DescribeTags", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result, _ := ret.GetArray("Tags", "Tag")
|
||||
for _, item := range result {
|
||||
k, _ := item.GetString("TagKey")
|
||||
v, _ := item.Get("TagValue")
|
||||
if len(k) > 0 {
|
||||
tags.Set(k, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tags, nil
|
||||
}
|
||||
|
||||
func (self *SInstance) GetMetadata() *jsonutils.JSONDict {
|
||||
data := jsonutils.NewDict()
|
||||
|
||||
@@ -161,6 +213,12 @@ func (self *SInstance) GetMetadata() *jsonutils.JSONDict {
|
||||
priceKey := fmt.Sprintf("%s::%s::%s::%s::%s", self.RegionId, self.InstanceType, self.InstanceNetworkType, self.OSType, optimized)
|
||||
data.Add(jsonutils.NewString(priceKey), "price_key")
|
||||
|
||||
tags, err := self.host.zone.region.fetchTags("instance", self.InstanceId)
|
||||
if err != nil {
|
||||
log.Errorf(err.Error())
|
||||
}
|
||||
data.Update(tags)
|
||||
|
||||
if len(self.ImageId) > 0 {
|
||||
if image, err := self.host.zone.region.GetImage(self.ImageId); err != nil {
|
||||
log.Errorf("Failed to find image %s for instance %s", self.ImageId, self.GetName())
|
||||
|
||||
@@ -156,7 +156,6 @@ func init() {
|
||||
return e
|
||||
}
|
||||
|
||||
// todo : add create disks
|
||||
err := cli.ChangeVMConfig(instance.ZoneId, args.ID, args.Ncpu, args.Vmem, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"github.com/coredns/coredns/plugin/pkg/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
|
||||
sdk "github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
)
|
||||
|
||||
const (
|
||||
CLOUD_PROVIDER_AWS = models.CLOUD_PROVIDER_AWS
|
||||
CLOUD_PROVIDER_AWS_CN = "AWS"
|
||||
|
||||
AWS_INTERNATIONAL_DEFAULT_REGION = "us-west-1"
|
||||
AWS_CHINA_DEFAULT_REGION = "cn-north-1"
|
||||
AWS_API_VERSION = "2018-10-10"
|
||||
)
|
||||
|
||||
type SAwsClient struct {
|
||||
providerId string
|
||||
providerName string
|
||||
accessUrl string // 服务区域 ChinaCloud | InternationalCloud
|
||||
accessKey string
|
||||
secret string
|
||||
iregions []cloudprovider.ICloudRegion
|
||||
}
|
||||
|
||||
func NewAwsClient(providerId string, providerName string, accessUrl string, accessKey string, secret string) (*SAwsClient, error) {
|
||||
client := SAwsClient{providerId: providerId, providerName: providerName, accessUrl: accessUrl, accessKey: accessKey, secret: secret}
|
||||
err := client.fetchRegions()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &client, nil
|
||||
}
|
||||
|
||||
func (self *SAwsClient) getDefaultSession() (*session.Session, error) {
|
||||
defaultRegion := AWS_INTERNATIONAL_DEFAULT_REGION
|
||||
switch self.accessUrl {
|
||||
case "InternationalCloud":
|
||||
defaultRegion = AWS_INTERNATIONAL_DEFAULT_REGION
|
||||
case "ChinaCloud":
|
||||
defaultRegion = AWS_CHINA_DEFAULT_REGION
|
||||
}
|
||||
return session.NewSession(&sdk.Config{
|
||||
Region: sdk.String(defaultRegion),
|
||||
Credentials: credentials.NewStaticCredentials(self.accessKey, self.secret, ""),
|
||||
})
|
||||
}
|
||||
|
||||
func (self *SAwsClient) GetSubAccounts() ([]cloudprovider.SSubAccount, error) {
|
||||
// todo: implement me
|
||||
err := self.fetchRegions()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
subAccount := cloudprovider.SSubAccount{}
|
||||
subAccount.Name = self.providerName
|
||||
subAccount.Account = self.accessKey
|
||||
return []cloudprovider.SSubAccount{subAccount}, nil
|
||||
}
|
||||
|
||||
func (self *SAwsClient) UpdateAccount(accessKey, secret string) error {
|
||||
if self.accessKey != accessKey || self.secret != secret {
|
||||
self.accessKey = accessKey
|
||||
self.secret = secret
|
||||
return self.fetchRegions()
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// 用于初始化region信息
|
||||
func (self *SAwsClient) fetchRegions() error {
|
||||
s, err := self.getDefaultSession()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
svc := ec2.New(s)
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/service/ec2/#EC2.DescribeRegions
|
||||
result, err := svc.DescribeRegions(&ec2.DescribeRegionsInput{})
|
||||
log.Debugf("remote regions: %s", result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
regions := make([]SRegion, 0)
|
||||
// empty iregions
|
||||
if self.iregions != nil {
|
||||
self.iregions = self.iregions[:0]
|
||||
}
|
||||
|
||||
for _, region := range result.Regions {
|
||||
name := *region.RegionName
|
||||
endpoint := *region.Endpoint
|
||||
sregion := SRegion{client: self, RegionId: name, RegionEndpoint: endpoint}
|
||||
// 初始化region client
|
||||
sregion.getEc2Client()
|
||||
regions = append(regions, sregion)
|
||||
self.iregions = append(self.iregions, &sregion)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 只是使用fetchRegions初始化好的self.iregions. 本身并不从云服务器厂商拉取region信息
|
||||
func (self *SAwsClient) GetRegions() []SRegion {
|
||||
regions := make([]SRegion, len(self.iregions))
|
||||
for i := 0; i < len(regions); i += 1 {
|
||||
region := self.iregions[i].(*SRegion)
|
||||
regions[i] = *region
|
||||
}
|
||||
return regions
|
||||
}
|
||||
|
||||
func (self *SAwsClient) GetIRegions() []cloudprovider.ICloudRegion {
|
||||
return self.iregions
|
||||
}
|
||||
|
||||
func (self *SAwsClient) GetRegion(regionId string) *SRegion {
|
||||
if len(regionId) == 0 {
|
||||
regionId = AWS_INTERNATIONAL_DEFAULT_REGION
|
||||
switch self.accessUrl {
|
||||
case "InternationalCloud":
|
||||
regionId = AWS_INTERNATIONAL_DEFAULT_REGION
|
||||
case "ChinaCloud":
|
||||
regionId = AWS_CHINA_DEFAULT_REGION
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(self.iregions); i += 1 {
|
||||
if self.iregions[i].GetId() == regionId {
|
||||
return self.iregions[i].(*SRegion)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAwsClient) GetIRegionById(id string) (cloudprovider.ICloudRegion, error) {
|
||||
for i := 0; i < len(self.iregions); i += 1 {
|
||||
if self.iregions[i].GetGlobalId() == id {
|
||||
return self.iregions[i], nil
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SAwsClient) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
|
||||
for i := 0; i < len(self.iregions); i += 1 {
|
||||
ihost, err := self.iregions[i].GetIHostById(id)
|
||||
if err == nil {
|
||||
return ihost, nil
|
||||
} else if err != cloudprovider.ErrNotFound {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SAwsClient) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) {
|
||||
for i := 0; i < len(self.iregions); i += 1 {
|
||||
ihost, err := self.iregions[i].GetIVpcById(id)
|
||||
if err == nil {
|
||||
return ihost, nil
|
||||
} else if err != cloudprovider.ErrNotFound {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SAwsClient) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
|
||||
for i := 0; i < len(self.iregions); i += 1 {
|
||||
ihost, err := self.iregions[i].GetIStorageById(id)
|
||||
if err == nil {
|
||||
return ihost, nil
|
||||
} else if err != cloudprovider.ErrNotFound {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SAwsClient) GetIStoragecacheById(id string) (cloudprovider.ICloudStoragecache, error) {
|
||||
for i := 0; i < len(self.iregions); i += 1 {
|
||||
ihost, err := self.iregions[i].GetIStoragecacheById(id)
|
||||
if err == nil {
|
||||
return ihost, nil
|
||||
} else if err != cloudprovider.ErrNotFound {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
type SAccountBalance struct {
|
||||
AvailableAmount float64
|
||||
AvailableCashAmount float64
|
||||
CreditAmount float64
|
||||
MybankCreditAmount float64
|
||||
Currency string
|
||||
}
|
||||
|
||||
func (self *SAwsClient) QueryAccountBalance() (*SAccountBalance, error) {
|
||||
// todo: aws 貌似没有余额?
|
||||
panic("implement me")
|
||||
}
|
||||
@@ -0,0 +1,393 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/coredns/coredns/plugin/pkg/log"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
type SMountInstances struct {
|
||||
MountInstance []string
|
||||
}
|
||||
|
||||
type STags struct {
|
||||
Tag []string
|
||||
}
|
||||
|
||||
type SDisk struct {
|
||||
storage *SStorage
|
||||
|
||||
RegionId string
|
||||
ZoneId string // AvailabilityZone
|
||||
DiskId string // VolumeId
|
||||
|
||||
DiskName string // Tag Name
|
||||
Size int // Size
|
||||
Category string // VolumeType
|
||||
Type string // system | data
|
||||
Status string // State
|
||||
AttachmentStatus string // attachment.status
|
||||
Device string // Device
|
||||
InstanceId string // InstanceId
|
||||
Encrypted bool // Encrypted
|
||||
SourceSnapshotId string // SnapshotId
|
||||
Iops int // Iops
|
||||
Tags TagSpec
|
||||
|
||||
CreationTime time.Time // CreateTime
|
||||
AttachedTime time.Time // AttachTime
|
||||
DetachedTime time.Time
|
||||
|
||||
DeleteWithInstance bool // DeleteOnTermination
|
||||
EnableAutoSnapshot bool
|
||||
EnableAutomatedSnapshotPolicy bool
|
||||
|
||||
/*下面这些字段也许不需要*/
|
||||
AutoSnapshotPolicyId string
|
||||
DeleteAutoSnapshot bool
|
||||
Description string
|
||||
DiskChargeType InstanceChargeType
|
||||
ExpiredTime time.Time
|
||||
ImageId string
|
||||
MountInstances SMountInstances
|
||||
Portable bool
|
||||
ProductCode string
|
||||
ResourceGroupId string
|
||||
}
|
||||
|
||||
func (self *SDisk) GetId() string {
|
||||
return self.DiskId
|
||||
}
|
||||
|
||||
func (self *SDisk) GetName() string {
|
||||
if len(self.DiskName) > 0 {
|
||||
return self.DiskName
|
||||
}
|
||||
return self.DiskId
|
||||
}
|
||||
|
||||
func (self *SDisk) GetGlobalId() string {
|
||||
return self.DiskId
|
||||
}
|
||||
|
||||
func (self *SDisk) GetStatus() string {
|
||||
// creating | available | in-use | deleting | deleted | error
|
||||
switch self.Status {
|
||||
case "creating":
|
||||
return models.DISK_ALLOCATING
|
||||
case "deleting":
|
||||
return models.DISK_DEALLOC
|
||||
case "error":
|
||||
return models.DISK_ALLOC_FAILED
|
||||
default:
|
||||
return models.DISK_READY
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SDisk) Refresh() error {
|
||||
new, err := self.storage.zone.region.GetDisk(self.DiskId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(self, new)
|
||||
}
|
||||
|
||||
func (self *SDisk) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SDisk) GetMetadata() *jsonutils.JSONDict {
|
||||
data := jsonutils.NewDict()
|
||||
data.Add(jsonutils.NewString(models.HYPERVISOR_AWS), "hypervisor")
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
func (self *SDisk) GetBillingType() string {
|
||||
// todo: implement me
|
||||
return models.BILLING_TYPE_PREPAID
|
||||
}
|
||||
|
||||
func (self *SDisk) GetExpiredAt() time.Time {
|
||||
return self.ExpiredTime
|
||||
}
|
||||
|
||||
func (self *SDisk) GetIStorge() cloudprovider.ICloudStorage {
|
||||
return self.storage
|
||||
}
|
||||
|
||||
func (self *SDisk) GetDiskFormat() string {
|
||||
return "vhd"
|
||||
}
|
||||
|
||||
func (self *SDisk) GetDiskSizeMB() int {
|
||||
return self.Size * 1024
|
||||
}
|
||||
|
||||
func (self *SDisk) GetIsAutoDelete() bool {
|
||||
return self.DeleteWithInstance
|
||||
}
|
||||
|
||||
func (self *SDisk) GetTemplateId() string {
|
||||
return self.ImageId
|
||||
}
|
||||
|
||||
func (self *SDisk) GetDiskType() string {
|
||||
return self.Type
|
||||
}
|
||||
|
||||
func (self *SDisk) GetFsFormat() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SDisk) GetIsNonPersistent() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SDisk) GetDriver() string {
|
||||
return "scsi"
|
||||
}
|
||||
|
||||
func (self *SDisk) GetCacheMode() string {
|
||||
return "none"
|
||||
}
|
||||
|
||||
func (self *SDisk) GetMountpoint() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SDisk) Delete() error {
|
||||
if _, err := self.storage.zone.region.GetDisk(self.DiskId); err == cloudprovider.ErrNotFound {
|
||||
log.Errorf("Failed to find disk %s when delete", self.DiskId)
|
||||
return nil
|
||||
}
|
||||
return self.storage.zone.region.DeleteDisk(self.DiskId)
|
||||
}
|
||||
|
||||
func (self *SDisk) CreateISnapshot(name string, desc string) (cloudprovider.ICloudSnapshot, error) {
|
||||
if snapshotId, err := self.storage.zone.region.CreateSnapshot(self.DiskId, name, desc); err != nil {
|
||||
log.Errorf("createSnapshot fail %s", err)
|
||||
return nil, err
|
||||
} else if snapshot, err := self.getSnapshot(snapshotId); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
snapshot.region = self.storage.zone.region
|
||||
if err := cloudprovider.WaitStatus(snapshot, models.SNAPSHOT_READY, 15*time.Second, 3600*time.Second); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return snapshot, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SDisk) GetISnapshot(snapshotId string) (cloudprovider.ICloudSnapshot, error) {
|
||||
if snapshot, err := self.getSnapshot(snapshotId); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
snapshot.region = self.storage.zone.region
|
||||
return snapshot, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SDisk) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
|
||||
snapshots := make([]SSnapshot, 0)
|
||||
for {
|
||||
if parts, total, err := self.storage.zone.region.GetSnapshots("", self.DiskId, "", []string{}, 0, 20); err != nil {
|
||||
log.Errorf("GetDisks fail %s", err)
|
||||
return nil, err
|
||||
} else {
|
||||
snapshots = append(snapshots, parts...)
|
||||
if len(snapshots) >= total {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
isnapshots := make([]cloudprovider.ICloudSnapshot, len(snapshots))
|
||||
for i := 0; i < len(snapshots); i++ {
|
||||
snapshots[i].region = self.storage.zone.region
|
||||
isnapshots[i] = &snapshots[i]
|
||||
}
|
||||
return isnapshots, nil
|
||||
}
|
||||
|
||||
func (self *SDisk) Resize(newSize int64) error {
|
||||
return self.storage.zone.region.resizeDisk(self.DiskId, newSize)
|
||||
}
|
||||
|
||||
func (self *SDisk) Reset(snapshotId string) error {
|
||||
return self.storage.zone.region.resetDisk(self.DiskId, snapshotId)
|
||||
}
|
||||
|
||||
func (self *SDisk) getSnapshot(snapshotId string) (*SSnapshot, error) {
|
||||
if snapshots, total, err := self.storage.zone.region.GetSnapshots("", "", "", []string{snapshotId}, 0, 1); err != nil {
|
||||
return nil, err
|
||||
} else if total != 1 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
} else {
|
||||
return &snapshots[0], nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) GetDisks(instanceId string, zoneId string, storageType string, diskIds []string, offset int, limit int) ([]SDisk, int, error) {
|
||||
params := &ec2.DescribeVolumesInput{}
|
||||
filters := make([]*ec2.Filter, 0)
|
||||
if len(instanceId) > 0 {
|
||||
filters = AppendSingleValueFilter(filters, "attachment.instance-id", instanceId)
|
||||
}
|
||||
|
||||
if len(zoneId) > 0 {
|
||||
filters = AppendSingleValueFilter(filters, "availability-zone", zoneId)
|
||||
}
|
||||
|
||||
if len(storageType) > 0 {
|
||||
filters = AppendSingleValueFilter(filters, "volume-type", storageType)
|
||||
}
|
||||
|
||||
if len(filters) > 0 {
|
||||
params.SetFilters(filters)
|
||||
}
|
||||
|
||||
if len(diskIds) > 0 {
|
||||
params.SetVolumeIds(ConvertedList(diskIds))
|
||||
}
|
||||
|
||||
ret, err := self.ec2Client.DescribeVolumes(params)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
disks := []SDisk{}
|
||||
for _, item := range ret.Volumes {
|
||||
if err := FillZero(item); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
tagspec := TagSpec{}
|
||||
tagspec.LoadingEc2Tags(item.Tags)
|
||||
|
||||
disk := SDisk{}
|
||||
disk.ZoneId = *item.AvailabilityZone
|
||||
disk.Status = *item.State
|
||||
disk.DiskName = tagspec.GetNameTag()
|
||||
disk.Size = int(*item.Size)
|
||||
disk.Category = *item.VolumeType
|
||||
disk.RegionId = self.RegionId
|
||||
disk.SourceSnapshotId = *item.SnapshotId
|
||||
disk.Encrypted = *item.Encrypted
|
||||
disk.DiskId = *item.VolumeId
|
||||
disk.Iops = int(*item.Iops)
|
||||
disk.CreationTime = *item.CreateTime
|
||||
disk.Tags = tagspec
|
||||
if len(item.Attachments) > 0 {
|
||||
disk.DeleteWithInstance = *item.Attachments[0].DeleteOnTermination
|
||||
disk.AttachedTime = *item.Attachments[0].AttachTime
|
||||
disk.AttachmentStatus = *item.Attachments[0].State
|
||||
disk.Device = StrVal(item.Attachments[0].Device)
|
||||
disk.InstanceId = StrVal(item.Attachments[0].InstanceId)
|
||||
// todo: 需要通过describe-instances 的root device 判断是否是系统盘
|
||||
// todo: 系统盘需要放在返回disks列表的首位
|
||||
if len(disk.InstanceId) > 0 {
|
||||
instance, err := self.GetInstance(disk.InstanceId)
|
||||
if err != nil {
|
||||
log.Debug(err)
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if disk.Device == instance.RootDeviceName {
|
||||
disk.Type = models.DISK_TYPE_SYS
|
||||
} else {
|
||||
disk.Type = models.DISK_TYPE_DATA
|
||||
}
|
||||
} else {
|
||||
disk.Type = models.DISK_TYPE_DATA
|
||||
}
|
||||
}
|
||||
|
||||
disks = append(disks, disk)
|
||||
}
|
||||
return disks, len(disks), nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetDisk(diskId string) (*SDisk, error) {
|
||||
disks, total, err := self.GetDisks("", "", "", []string{diskId}, 0, 1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if total != 1 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return &disks[0], nil
|
||||
}
|
||||
|
||||
func (self *SRegion) DeleteDisk(diskId string) error {
|
||||
disk, err := self.GetDisk(diskId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if disk.Status != ec2.VolumeStateAvailable {
|
||||
return fmt.Errorf("disk status not in %s", ec2.VolumeStateAvailable)
|
||||
}
|
||||
params := &ec2.DeleteVolumeInput{}
|
||||
if len(diskId) <= 0 {
|
||||
return fmt.Errorf("disk id should not be empty")
|
||||
}
|
||||
|
||||
params.SetVolumeId(diskId)
|
||||
_, err = self.ec2Client.DeleteVolume(params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SRegion) resizeDisk(diskId string, size int64) error {
|
||||
// https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/volume_constraints.html
|
||||
// MBR -> 2 TiB
|
||||
// GPT -> 16 TiB
|
||||
// size unit GiB
|
||||
params := &ec2.ModifyVolumeInput{}
|
||||
if size > 0 {
|
||||
params.SetSize(size)
|
||||
} else {
|
||||
return fmt.Errorf("size should great than 0")
|
||||
}
|
||||
|
||||
if len(diskId) <= 0 {
|
||||
return fmt.Errorf("disk id should not be empty")
|
||||
} else {
|
||||
params.SetVolumeId(diskId)
|
||||
}
|
||||
|
||||
_, err := self.ec2Client.ModifyVolume(params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SRegion) resetDisk(diskId, snapshotId string) error {
|
||||
// aws貌似不支持直接重置
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateDisk(zoneId string, category string, name string, sizeGb int, snapshotId string, desc string) (string, error) {
|
||||
tagspec := TagSpec{ResourceType: "volume"}
|
||||
tagspec.SetNameTag(name)
|
||||
tagspec.SetDescTag(desc)
|
||||
ec2Tags, _ := tagspec.GetTagSpecifications()
|
||||
|
||||
params := &ec2.CreateVolumeInput{}
|
||||
params.SetAvailabilityZone(zoneId)
|
||||
params.SetVolumeType(category)
|
||||
params.SetSize(int64(sizeGb))
|
||||
if len(snapshotId) > 0 {
|
||||
params.SetSnapshotId(snapshotId)
|
||||
}
|
||||
params.SetTagSpecifications([]*ec2.TagSpecification{ec2Tags})
|
||||
|
||||
ret, err := self.ec2Client.CreateVolume(params)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return StrVal(ret.VolumeId), nil
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
const (
|
||||
EIP_STATUS_INUSE = "InUse"
|
||||
EIP_STATUS_AVAILABLE = "Available"
|
||||
)
|
||||
|
||||
type SEipAddress struct {
|
||||
region *SRegion
|
||||
|
||||
AllocationId string
|
||||
Bandwidth int
|
||||
Tags TagSpec
|
||||
Status string
|
||||
InstanceId string
|
||||
AssociationId string
|
||||
Domain string
|
||||
NetworkInterfaceId string
|
||||
NetworkInterfaceOwnerId string
|
||||
PrivateIpAddress string
|
||||
IpAddress string
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetId() string {
|
||||
return self.AllocationId
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetName() string {
|
||||
return self.IpAddress
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetGlobalId() string {
|
||||
return self.AllocationId
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetStatus() string {
|
||||
switch self.Status {
|
||||
// todo: EIP_STATUS_INUSE 对应READY?
|
||||
case EIP_STATUS_AVAILABLE, EIP_STATUS_INUSE:
|
||||
return models.EIP_STATUS_READY
|
||||
default:
|
||||
return models.EIP_STATUS_UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SEipAddress) Refresh() error {
|
||||
if self.IsEmulated() {
|
||||
return nil
|
||||
}
|
||||
new, err := self.region.GetEip(self.AllocationId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(self, new)
|
||||
}
|
||||
|
||||
func (self *SEipAddress) IsEmulated() bool {
|
||||
if self.AllocationId == self.InstanceId {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetMetadata() *jsonutils.JSONDict {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetIpAddr() string {
|
||||
return self.IpAddress
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetMode() string {
|
||||
if self.InstanceId == self.AllocationId {
|
||||
return models.EIP_MODE_INSTANCE_PUBLICIP
|
||||
} else {
|
||||
return models.EIP_MODE_STANDALONE_EIP
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetAssociationType() string {
|
||||
// todo : ?
|
||||
return "server"
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetAssociationExternalId() string {
|
||||
return self.InstanceId
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetBandwidth() int {
|
||||
return self.Bandwidth
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetInternetChargeType() string {
|
||||
// todo : implement me
|
||||
return models.EIP_CHARGE_TYPE_BY_TRAFFIC
|
||||
}
|
||||
|
||||
func (self *SEipAddress) GetManagerId() string {
|
||||
return self.region.client.providerId
|
||||
}
|
||||
|
||||
func (self *SEipAddress) Delete() error {
|
||||
return self.region.DeallocateEIP(self.AllocationId)
|
||||
}
|
||||
|
||||
func (self *SEipAddress) Associate(instanceId string) error {
|
||||
err := self.region.AssociateEip(self.AllocationId, instanceId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = cloudprovider.WaitStatus(self, models.EIP_STATUS_READY, 10*time.Second, 180*time.Second)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SEipAddress) Dissociate() error {
|
||||
err := self.region.DissociateEip(self.AllocationId, self.InstanceId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = cloudprovider.WaitStatus(self, models.EIP_STATUS_READY, 10*time.Second, 180*time.Second)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SEipAddress) ChangeBandwidth(bw int) error {
|
||||
return self.region.UpdateEipBandwidth(self.AllocationId, bw)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetEips(eipId string, offset int, limit int) ([]SEipAddress, int, error) {
|
||||
params := ec2.DescribeAddressesInput{}
|
||||
if len(eipId) > 0 {
|
||||
params.SetAllocationIds([]*string{&eipId})
|
||||
}
|
||||
|
||||
res, err := self.ec2Client.DescribeAddresses(¶ms)
|
||||
if err != nil {
|
||||
log.Errorf("DescribeEipAddresses fail %s", err)
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
eips := make([]SEipAddress, 0)
|
||||
for _, ip := range res.Addresses {
|
||||
if err := FillZero(ip); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
tagspec := TagSpec{ResourceType: "eip"}
|
||||
tagspec.LoadingEc2Tags(ip.Tags)
|
||||
|
||||
var status string
|
||||
if len(*ip.AssociationId) > 0 {
|
||||
status = EIP_STATUS_INUSE
|
||||
} else {
|
||||
status = EIP_STATUS_AVAILABLE
|
||||
}
|
||||
|
||||
eips = append(eips, SEipAddress{
|
||||
region: self,
|
||||
AllocationId: *ip.AllocationId,
|
||||
Tags: tagspec,
|
||||
Status: status,
|
||||
InstanceId: *ip.InstanceId,
|
||||
AssociationId: *ip.AssociationId,
|
||||
Domain: *ip.Domain,
|
||||
NetworkInterfaceId: *ip.NetworkInterfaceId,
|
||||
NetworkInterfaceOwnerId: *ip.NetworkInterfaceOwnerId,
|
||||
PrivateIpAddress: *ip.PrivateIpAddress,
|
||||
IpAddress: *ip.PublicIp,
|
||||
})
|
||||
}
|
||||
return eips, len(eips), nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetEip(eipId string) (*SEipAddress, error) {
|
||||
eips, total, err := self.GetEips(eipId, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if total != 1 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return &eips[0], nil
|
||||
}
|
||||
|
||||
func (self *SRegion) AllocateEIP(domainType string) (*SEipAddress, error) {
|
||||
params := &ec2.AllocateAddressInput{}
|
||||
params.SetDomain(domainType)
|
||||
eip, err := self.ec2Client.AllocateAddress(params)
|
||||
if err != nil {
|
||||
log.Errorf("AllocateEipAddress fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = self.fetchInfrastructure()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return self.GetEip(*eip.AllocationId)
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateEIP(name string, bwMbps int, chargeType string) (cloudprovider.ICloudEIP, error) {
|
||||
// todo: aws 不支持指定bwMbps, chargeType ?
|
||||
log.Debugf("CreateEip: aws not support specific params name/bwMbps/chargeType.")
|
||||
return self.AllocateEIP("vpc")
|
||||
}
|
||||
|
||||
func (self *SRegion) DeallocateEIP(eipId string) error {
|
||||
params := &ec2.ReleaseAddressInput{}
|
||||
params.SetAllocationId(eipId)
|
||||
_, err := self.ec2Client.ReleaseAddress(params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SRegion) AssociateEip(eipId string, instanceId string) error {
|
||||
params := &ec2.AssociateAddressInput{}
|
||||
params.SetAllocationId(eipId)
|
||||
params.SetInstanceId(instanceId)
|
||||
_, err := self.ec2Client.AssociateAddress(params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SRegion) DissociateEip(eipId string, instanceId string) error {
|
||||
eip, err := self.GetEip(eipId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(eip.AssociationId) == 0 {
|
||||
// 已经是解绑状态
|
||||
return nil
|
||||
}
|
||||
|
||||
if eip.InstanceId != instanceId {
|
||||
return fmt.Errorf("eip %s associate with another instance %s", eipId, eip.InstanceId)
|
||||
}
|
||||
|
||||
params := &ec2.DisassociateAddressInput{}
|
||||
params.SetAssociationId(eip.AssociationId)
|
||||
_, err = self.ec2Client.DisassociateAddress(params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SRegion) UpdateEipBandwidth(eipId string, bw int) error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
type SHost struct {
|
||||
zone *SZone
|
||||
}
|
||||
|
||||
func (self *SHost) GetId() string {
|
||||
return fmt.Sprintf("%s-%s", self.zone.region.client.providerId, self.zone.GetId())
|
||||
}
|
||||
|
||||
func (self *SHost) GetName() string {
|
||||
return fmt.Sprintf("%s-%s", self.zone.region.client.providerName, self.zone.GetId())
|
||||
}
|
||||
|
||||
func (self *SHost) GetGlobalId() string {
|
||||
return fmt.Sprintf("%s-%s", self.zone.region.client.providerId, self.zone.GetId())
|
||||
}
|
||||
|
||||
func (self *SHost) GetStatus() string {
|
||||
return models.HOST_STATUS_RUNNING
|
||||
}
|
||||
|
||||
func (self *SHost) Refresh() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SHost) IsEmulated() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SHost) GetMetadata() *jsonutils.JSONDict {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SHost) GetIVMs() ([]cloudprovider.ICloudVM, error) {
|
||||
vms := make([]SInstance, 0)
|
||||
vms, _, err := self.zone.region.GetInstances(self.zone.ZoneId, nil, len(vms), 50)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ivms := make([]cloudprovider.ICloudVM, len(vms))
|
||||
for i := 0; i < len(vms); i += 1 {
|
||||
vms[i].host = self
|
||||
ivms[i] = &vms[i]
|
||||
}
|
||||
return ivms, nil
|
||||
}
|
||||
|
||||
func (self *SHost) GetIVMById(gid string) (cloudprovider.ICloudVM, error) {
|
||||
log.Debugf("GetIVMById %s", gid)
|
||||
ivms, _, err := self.zone.region.GetInstances(self.zone.ZoneId, []string{gid}, 0, 1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(ivms) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
if len(ivms) > 1 {
|
||||
return nil, cloudprovider.ErrDuplicateId
|
||||
}
|
||||
ivms[0].host = self
|
||||
return &ivms[0], nil
|
||||
}
|
||||
|
||||
func (self *SHost) GetIWires() ([]cloudprovider.ICloudWire, error) {
|
||||
return self.zone.GetIWires()
|
||||
}
|
||||
|
||||
func (self *SHost) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
|
||||
return self.zone.GetIStorages()
|
||||
}
|
||||
|
||||
func (self *SHost) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
|
||||
return self.zone.GetIStorageById(id)
|
||||
}
|
||||
|
||||
func (self *SHost) GetEnabled() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SHost) GetHostStatus() string {
|
||||
return models.HOST_ONLINE
|
||||
}
|
||||
|
||||
func (self *SHost) GetAccessIp() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SHost) GetAccessMac() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SHost) GetSysInfo() jsonutils.JSONObject {
|
||||
info := jsonutils.NewDict()
|
||||
info.Add(jsonutils.NewString(CLOUD_PROVIDER_AWS), "manufacture")
|
||||
return info
|
||||
}
|
||||
|
||||
func (self *SHost) GetSN() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SHost) GetCpuCount() int8 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SHost) GetNodeCount() int8 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SHost) GetCpuDesc() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SHost) GetCpuMhz() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SHost) GetMemSizeMB() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SHost) GetStorageSizeMB() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SHost) GetStorageType() string {
|
||||
return models.DISK_TYPE_HYBRID
|
||||
}
|
||||
|
||||
func (self *SHost) GetHostType() string {
|
||||
return models.HOST_TYPE_AWS
|
||||
}
|
||||
|
||||
func (self *SHost) GetManagerId() string {
|
||||
return self.zone.region.client.providerId
|
||||
}
|
||||
|
||||
func (self *SHost) GetInstanceById(instanceId string) (*SInstance, error) {
|
||||
inst, err := self.zone.region.GetInstance(instanceId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inst.host = self
|
||||
return inst, nil
|
||||
}
|
||||
|
||||
func (self *SHost) CreateVM(name, imgId string, sysDiskSize, cpu, memMB int, networkId, ipAddr, desc,
|
||||
passwd, storageType string, diskSizes []int, publicKey string, secgroupId string, userData string) (cloudprovider.ICloudVM, error) {
|
||||
if len(publicKey) == 0 {
|
||||
return nil, fmt.Errorf("AWS instance create error: keypair required")
|
||||
}
|
||||
|
||||
if len(passwd) > 0 {
|
||||
log.Debugf("Ignored: AWS not support password.Use keypair instand")
|
||||
}
|
||||
|
||||
vmId, err := self._createVM(name, imgId, sysDiskSize, cpu, memMB, networkId, ipAddr, desc, passwd, storageType, diskSizes, publicKey, secgroupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vm, err := self.GetInstanceById(vmId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return vm, err
|
||||
}
|
||||
|
||||
func (self *SHost) _createVM(name, imgId string, sysDiskSize, cpu, memMB int,
|
||||
networkId, ipAddr, desc, passwd,
|
||||
storageType string, diskSizes []int, publicKey string, secgroupId string) (string, error) {
|
||||
// 网络配置及安全组绑定
|
||||
net := self.zone.getNetworkById(networkId)
|
||||
if net == nil {
|
||||
return "", fmt.Errorf("invalid network ID %s", networkId)
|
||||
}
|
||||
|
||||
if net.wire == nil {
|
||||
log.Errorf("network's wire is empty")
|
||||
return "", fmt.Errorf("network's wire is empty")
|
||||
}
|
||||
|
||||
if net.wire.vpc == nil {
|
||||
log.Errorf("wire's vpc is empty")
|
||||
return "", fmt.Errorf("wire's vpc is empty")
|
||||
}
|
||||
|
||||
if len(secgroupId) == 0 {
|
||||
secgroups, err := net.wire.vpc.GetISecurityGroups()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("get security group error %s", err)
|
||||
}
|
||||
|
||||
if len(secgroups) == 0 {
|
||||
// aws 默认就已经创建好了一个默认安全组。正常情况下并不需要手动创建
|
||||
secId, err := self.zone.region.createDefaultSecurityGroup(net.wire.vpc.VpcId)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("no secgroup for vpc and failed to create a default One!!")
|
||||
} else {
|
||||
secgroupId = secId
|
||||
}
|
||||
} else {
|
||||
secgroupId = secgroups[0].GetId()
|
||||
}
|
||||
}
|
||||
// 同步keypair
|
||||
keypair := ""
|
||||
if len(publicKey) <= 0 {
|
||||
return "", fmt.Errorf("publickey should not be empty")
|
||||
}
|
||||
|
||||
keypair, err := self.zone.region.syncKeypair(publicKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// 镜像及硬盘配置
|
||||
img, err := self.zone.region.GetImage(imgId)
|
||||
if err != nil {
|
||||
log.Errorf("getiamge fail %s", err)
|
||||
return "", err
|
||||
}
|
||||
if img.Status != ImageStatusAvailable {
|
||||
log.Errorf("image %s status %s", imgId, img.Status)
|
||||
return "", fmt.Errorf("image not ready")
|
||||
}
|
||||
|
||||
disks := make([]SDisk, len(diskSizes)+1)
|
||||
disks[0].Size = img.Size
|
||||
if sysDiskSize > 0 && sysDiskSize > img.Size {
|
||||
disks[0].Size = sysDiskSize
|
||||
}
|
||||
disks[0].Category = storageType
|
||||
|
||||
for i, sz := range diskSizes {
|
||||
disks[i+1].Size = sz
|
||||
disks[i+1].Category = storageType
|
||||
}
|
||||
|
||||
instanceTypes, err := self.zone.region.GetMatchInstanceTypes(cpu, memMB, 0, self.zone.ZoneId)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(instanceTypes) == 0 {
|
||||
return "", fmt.Errorf("instance type %dC%dMB not avaiable", cpu, memMB)
|
||||
}
|
||||
// 匹配实例类型
|
||||
for _, instType := range instanceTypes {
|
||||
instanceTypeId := instType.InstanceTypeId
|
||||
log.Debugf("Try instancetype : %s", instanceTypeId)
|
||||
vmId, err := self.zone.region.CreateInstance(name, imgId, instanceTypeId, networkId, secgroupId, self.zone.ZoneId, desc, disks, ipAddr, keypair)
|
||||
if err != nil {
|
||||
log.Errorf("Failed for %s: %s", instanceTypeId, err)
|
||||
} else {
|
||||
return vmId, nil
|
||||
}
|
||||
}
|
||||
// 创建实例
|
||||
return "", fmt.Errorf("Failed to create, specification not supported")
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
type ImageStatusType string
|
||||
|
||||
const (
|
||||
ImageStatusCreating ImageStatusType = "pending"
|
||||
ImageStatusAvailable ImageStatusType = "available"
|
||||
ImageStatusCreateFailed ImageStatusType = "failed"
|
||||
)
|
||||
|
||||
type ImageOwnerType string
|
||||
|
||||
const (
|
||||
ImageOwnerSystem ImageOwnerType = "amazon"
|
||||
ImageOwnerSelf ImageOwnerType = "self"
|
||||
ImageOwnerOthers ImageOwnerType = "microsoft"
|
||||
ImageOwnerMarketplace ImageOwnerType = "aws-marketplace"
|
||||
)
|
||||
|
||||
type ImageImportTask struct {
|
||||
ImageId string
|
||||
RegionId string
|
||||
TaskId string
|
||||
}
|
||||
|
||||
type RootDevice struct {
|
||||
SnapshotId string
|
||||
Size int // GB
|
||||
Category string // VolumeType
|
||||
}
|
||||
|
||||
type SImage struct {
|
||||
storageCache *SStoragecache
|
||||
|
||||
Architecture string
|
||||
CreationTime string
|
||||
Description string
|
||||
ImageId string
|
||||
ImageName string
|
||||
OSName string
|
||||
OSType string
|
||||
ImageType string
|
||||
IsSupportCloudinit bool
|
||||
IsSupportIoOptimized bool
|
||||
Platform string
|
||||
Size int
|
||||
Status ImageStatusType
|
||||
Usage string
|
||||
RootDevice RootDevice
|
||||
}
|
||||
|
||||
func (self *SImage) GetId() string {
|
||||
return self.ImageId
|
||||
}
|
||||
|
||||
func (self *SImage) GetName() string {
|
||||
return self.ImageName
|
||||
}
|
||||
|
||||
func (self *SImage) GetGlobalId() string {
|
||||
return self.ImageId
|
||||
}
|
||||
|
||||
func (self *SImage) GetStatus() string {
|
||||
switch self.Status {
|
||||
case ImageStatusCreating:
|
||||
return models.IMAGE_STATUS_QUEUED
|
||||
case ImageStatusAvailable:
|
||||
return models.IMAGE_STATUS_ACTIVE
|
||||
case ImageStatusCreateFailed:
|
||||
return models.IMAGE_STATUS_KILLED
|
||||
default:
|
||||
return models.IMAGE_STATUS_KILLED
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SImage) Refresh() error {
|
||||
// todo: GetImage
|
||||
new, err := self.storageCache.region.GetImage(self.ImageId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(self, new)
|
||||
}
|
||||
|
||||
func (self *SImage) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SImage) GetMetadata() *jsonutils.JSONDict {
|
||||
data := jsonutils.NewDict()
|
||||
if len(self.Architecture) > 0 {
|
||||
data.Add(jsonutils.NewString(self.Architecture), "os_arch")
|
||||
}
|
||||
if len(self.OSType) > 0 {
|
||||
data.Add(jsonutils.NewString(self.OSType), "os_name")
|
||||
}
|
||||
if len(self.Platform) > 0 {
|
||||
data.Add(jsonutils.NewString(self.Platform), "os_distribution")
|
||||
}
|
||||
if len(self.OSName) > 0 {
|
||||
data.Add(jsonutils.NewString(self.OSName), "os_version")
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func (self *SImage) Delete() error {
|
||||
// todo: implement me
|
||||
return self.storageCache.region.DeleteImage(self.ImageId)
|
||||
}
|
||||
|
||||
func (self *SImage) GetIStoragecache() cloudprovider.ICloudStoragecache {
|
||||
return self.storageCache
|
||||
}
|
||||
|
||||
func (self *SRegion) ImportImage(name string, osArch string, osType string, osDist string, diskFormat string, bucket string, key string) (*ImageImportTask, error) {
|
||||
params := &ec2.ImportImageInput{}
|
||||
params.SetArchitecture(osArch)
|
||||
params.SetHypervisor("xen") // todo: osType?
|
||||
params.SetPlatform(osType)
|
||||
// https://docs.aws.amazon.com/zh_cn/vm-import/latest/userguide/vmimport-image-import.html#import-vm-image
|
||||
params.SetRoleName("vmimport")
|
||||
container := &ec2.ImageDiskContainer{}
|
||||
container.SetDescription(fmt.Sprintf("vmimport %s", name))
|
||||
container.SetFormat(diskFormat)
|
||||
container.SetDeviceName("/dev/sda") // default /dev/sda
|
||||
bkt := &ec2.UserBucket{S3Bucket: &bucket, S3Key: &key}
|
||||
container.SetUserBucket(bkt)
|
||||
params.SetDiskContainers([]*ec2.ImageDiskContainer{container})
|
||||
params.SetLicenseType("BYOL") // todo: AWS?
|
||||
ret, err := self.ec2Client.ImportImage(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Debugf("ImportImage task: %s", ret.String())
|
||||
return &ImageImportTask{ImageId: StrVal(ret.ImageId), RegionId: self.RegionId, TaskId: *ret.ImportTaskId}, nil
|
||||
}
|
||||
|
||||
type ImageExportTask struct {
|
||||
ImageId string
|
||||
RegionId string
|
||||
TaskId string
|
||||
}
|
||||
|
||||
func (self *SRegion) ExportImage(instanceId string, imageId string) (*ImageExportTask, error) {
|
||||
params := &ec2.CreateInstanceExportTaskInput{}
|
||||
params.SetInstanceId(instanceId)
|
||||
params.SetDescription(fmt.Sprintf("image %s export from aws", imageId))
|
||||
params.SetTargetEnvironment("vmware")
|
||||
spec := &ec2.ExportToS3TaskSpecification{}
|
||||
spec.SetContainerFormat("ova")
|
||||
spec.SetDiskImageFormat("RAW")
|
||||
spec.SetS3Bucket("imgcache-onecloud")
|
||||
params.SetExportToS3Task(spec)
|
||||
ret, err := self.ec2Client.CreateInstanceExportTask(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ImageExportTask{ImageId: imageId, RegionId: self.RegionId, TaskId: *ret.ExportTask.ExportTaskId}, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetImage(imageId string) (*SImage, error) {
|
||||
images, _, err := self.GetImages("", ImageOwnerSelf, []string{imageId}, "", 0, 1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(images) == 0 {
|
||||
return nil, fmt.Errorf("image %s not found", imageId)
|
||||
}
|
||||
return &images[0], nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetImageByName(name string) (*SImage, error) {
|
||||
images, _, err := self.GetImages("", ImageOwnerSelf, nil, name, 0, 1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(images) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return &images[0], nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetImageStatus(imageId string) (ImageStatusType, error) {
|
||||
image, err := self.GetImage(imageId)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return image.Status, nil
|
||||
}
|
||||
|
||||
func getRootDiskSize(image *ec2.Image) (int, error) {
|
||||
rootDeivce := *image.RootDeviceName
|
||||
for _, volume := range image.BlockDeviceMappings {
|
||||
if len(rootDeivce) > 0 && *volume.DeviceName == rootDeivce {
|
||||
return int(*volume.Ebs.VolumeSize), nil
|
||||
}
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf("image size not found: %s", image.String())
|
||||
}
|
||||
|
||||
func (self *SRegion) GetImages(status ImageStatusType, owner ImageOwnerType, imageId []string, name string, offset int, limit int) ([]SImage, int, error) {
|
||||
params := &ec2.DescribeImagesInput{}
|
||||
filters := make([]*ec2.Filter, 0)
|
||||
if len(status) > 0 {
|
||||
filters = AppendSingleValueFilter(filters, "state", string(status))
|
||||
}
|
||||
|
||||
if len(name) > 0 {
|
||||
filters = AppendSingleValueFilter(filters, "name", name)
|
||||
}
|
||||
|
||||
if len(owner) > 0 {
|
||||
own := string(owner)
|
||||
params.SetOwners([]*string{&own})
|
||||
}
|
||||
|
||||
if len(imageId) > 0 {
|
||||
params.SetImageIds(ConvertedList(imageId))
|
||||
}
|
||||
ret, err := self.ec2Client.DescribeImages(params)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
images := []SImage{}
|
||||
for _, image := range ret.Images {
|
||||
if err := FillZero(image); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
tagspec := TagSpec{}
|
||||
tagspec.LoadingEc2Tags(image.Tags)
|
||||
|
||||
size, err := getRootDiskSize(image)
|
||||
if err != nil {
|
||||
log.Debugf(err.Error())
|
||||
}
|
||||
|
||||
var rootDevice RootDevice
|
||||
for _, block := range image.BlockDeviceMappings {
|
||||
if len(*image.RootDeviceName) > 0 && *block.DeviceName == *image.RootDeviceName {
|
||||
rootDevice.SnapshotId = *block.Ebs.SnapshotId
|
||||
rootDevice.Category = *block.Ebs.VolumeType
|
||||
rootDevice.Size = int(*block.Ebs.VolumeSize)
|
||||
}
|
||||
}
|
||||
|
||||
images = append(images, SImage{
|
||||
storageCache: self.getStoragecache(),
|
||||
Architecture: *image.Architecture,
|
||||
Description: *image.Description,
|
||||
ImageId: *image.ImageId,
|
||||
ImageName: tagspec.GetNameTag(),
|
||||
ImageType: *image.ImageType,
|
||||
IsSupportIoOptimized: *image.EnaSupport,
|
||||
Platform: *image.Platform,
|
||||
Status: ImageStatusType(*image.State),
|
||||
CreationTime: *image.CreationDate,
|
||||
Size: size,
|
||||
RootDevice: rootDevice,
|
||||
// Usage: "",
|
||||
// OSName: *image.Platform,
|
||||
})
|
||||
}
|
||||
|
||||
return images, len(images), nil
|
||||
}
|
||||
|
||||
func (self *SRegion) DeleteImage(imageId string) error {
|
||||
params := &ec2.DeregisterImageInput{}
|
||||
params.SetImageId(imageId)
|
||||
_, err := self.ec2Client.DeregisterImage(params)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,805 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/coredns/coredns/plugin/pkg/log"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/pkg/util/osprofile"
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
)
|
||||
|
||||
const (
|
||||
InstanceStatusPending = "pending"
|
||||
InstanceStatusRunning = "running"
|
||||
InstanceStatusShutting = "shutting-down"
|
||||
InstanceStatusTerminated = "terminated"
|
||||
InstanceStatusStopping = "stopping"
|
||||
InstanceStatusStopped = "stopped"
|
||||
)
|
||||
|
||||
type InstanceChargeType string
|
||||
|
||||
type SIpAddress struct {
|
||||
IpAddress []string
|
||||
}
|
||||
|
||||
type SNetworkInterfaces struct {
|
||||
NetworkInterface []SNetworkInterface
|
||||
}
|
||||
|
||||
type SNetworkInterface struct {
|
||||
MacAddress string
|
||||
NetworkInterfaceId string
|
||||
PrimaryIpAddress string // PrivateIpAddress
|
||||
}
|
||||
|
||||
type SSecurityGroupIds struct {
|
||||
SecurityGroupId []string
|
||||
}
|
||||
|
||||
type SVpcAttributes struct {
|
||||
PrivateIpAddress SIpAddress
|
||||
NetworkId string // subnet id
|
||||
VpcId string
|
||||
}
|
||||
|
||||
type SInstance struct {
|
||||
host *SHost
|
||||
RegionId string
|
||||
ZoneId string
|
||||
InstanceId string
|
||||
ImageId string
|
||||
|
||||
HostName string
|
||||
InstanceName string
|
||||
InstanceType string
|
||||
Cpu int8
|
||||
Memory int
|
||||
IoOptimized bool
|
||||
KeyPairName string
|
||||
CreationTime time.Time // LaunchTime
|
||||
ExpiredTime time.Time
|
||||
ProductCodes []string
|
||||
PublicDNSName string
|
||||
InnerIpAddress SIpAddress
|
||||
PublicIpAddress SIpAddress
|
||||
RootDeviceName string
|
||||
Status string // state
|
||||
VlanId string // subnet ID ?
|
||||
VpcAttributes SVpcAttributes
|
||||
SecurityGroupIds SSecurityGroupIds
|
||||
NetworkInterfaces SNetworkInterfaces
|
||||
EipAddress SEipAddress
|
||||
Disks []string
|
||||
DeviceNames []string
|
||||
OSName string
|
||||
OSType string
|
||||
Description string
|
||||
|
||||
// 这些貌似都没啥用
|
||||
// AutoReleaseTime string
|
||||
// DeviceAvailable bool
|
||||
// GPUAmount int
|
||||
// GPUSpec string
|
||||
// InstanceChargeType InstanceChargeType
|
||||
// InstanceNetworkType string
|
||||
// InstanceTypeFamily string
|
||||
// InternetChargeType string
|
||||
// InternetMaxBandwidthIn int
|
||||
// InternetMaxBandwidthOut int
|
||||
// OperationLocks SOperationLocks
|
||||
// Recyclable bool
|
||||
// SerialNumber string
|
||||
// SpotPriceLimit string
|
||||
// SpotStrategy string
|
||||
// StartTime time.Time
|
||||
// StoppedMode string
|
||||
}
|
||||
|
||||
func (self *SInstance) UpdateUserData(userData string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SInstance) GetId() string {
|
||||
return self.InstanceId
|
||||
}
|
||||
|
||||
func (self *SInstance) GetName() string {
|
||||
return self.InstanceName
|
||||
}
|
||||
|
||||
func (self *SInstance) GetGlobalId() string {
|
||||
return self.InstanceId
|
||||
}
|
||||
|
||||
func (self *SInstance) GetStatus() string {
|
||||
// todo : implement me
|
||||
switch self.Status {
|
||||
case InstanceStatusRunning:
|
||||
return models.VM_RUNNING
|
||||
case InstanceStatusPending: // todo: pending ?
|
||||
return models.VM_STARTING
|
||||
case InstanceStatusStopping:
|
||||
return models.VM_STOPPING
|
||||
case InstanceStatusStopped:
|
||||
return models.VM_READY
|
||||
default:
|
||||
return models.VM_UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SInstance) Refresh() error {
|
||||
new, err := self.host.zone.region.GetInstance(self.InstanceId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(self, new)
|
||||
}
|
||||
|
||||
func (self *SInstance) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SInstance) GetMetadata() *jsonutils.JSONDict {
|
||||
data := jsonutils.NewDict()
|
||||
// todo: add price_key here
|
||||
tags, err := FetchTags(self.host.zone.region.ec2Client, self.InstanceId)
|
||||
if err != nil {
|
||||
log.Errorf(err.Error())
|
||||
}
|
||||
data.Update(tags)
|
||||
|
||||
if len(self.ImageId) > 0 {
|
||||
if image, err := self.host.zone.region.GetImage(self.ImageId); err != nil {
|
||||
log.Errorf("Failed to find image %s for instance %s zone %s", self.ImageId, self.GetId(), self.ZoneId)
|
||||
} else if meta := image.GetMetadata(); meta != nil {
|
||||
data.Update(meta)
|
||||
}
|
||||
}
|
||||
for _, secgroupId := range self.SecurityGroupIds.SecurityGroupId {
|
||||
if len(secgroupId) > 0 {
|
||||
data.Add(jsonutils.NewString(secgroupId), "secgroupId")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
func (self *SInstance) GetBillingType() string {
|
||||
// todo: implement me
|
||||
return models.BILLING_TYPE_POSTPAID
|
||||
}
|
||||
|
||||
func (self *SInstance) GetExpiredAt() time.Time {
|
||||
return self.ExpiredTime
|
||||
}
|
||||
|
||||
func (self *SInstance) GetCreateTime() time.Time {
|
||||
return self.CreationTime
|
||||
}
|
||||
|
||||
func (self *SInstance) GetIHost() cloudprovider.ICloudHost {
|
||||
return self.host
|
||||
}
|
||||
|
||||
func (self *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
|
||||
disks, _, err := self.host.zone.region.GetDisks(self.InstanceId, "", "", nil, 0, 0)
|
||||
if err != nil {
|
||||
log.Errorf("fetchDisks fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
idisks := make([]cloudprovider.ICloudDisk, len(disks))
|
||||
for i := 0; i < len(disks); i += 1 {
|
||||
store, err := self.host.zone.getStorageByCategory(disks[i].Category)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disks[i].storage = store
|
||||
idisks[i] = &disks[i]
|
||||
}
|
||||
return idisks, nil
|
||||
}
|
||||
|
||||
func (self *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) {
|
||||
nics := make([]cloudprovider.ICloudNic, 0)
|
||||
for _, ip := range self.VpcAttributes.PrivateIpAddress.IpAddress {
|
||||
nic := SInstanceNic{instance: self, ipAddr: ip}
|
||||
nics = append(nics, &nic)
|
||||
}
|
||||
return nics, nil
|
||||
}
|
||||
|
||||
func (self *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) {
|
||||
// todo: implement me
|
||||
if len(self.PublicIpAddress.IpAddress) > 0 {
|
||||
eip := SEipAddress{}
|
||||
eip.region = self.host.zone.region
|
||||
eip.IpAddress = self.PublicIpAddress.IpAddress[0]
|
||||
eip.InstanceId = self.InstanceId
|
||||
eip.AllocationId = self.InstanceId // fixed
|
||||
eip.Bandwidth = 10000
|
||||
return &eip, nil
|
||||
} else if len(self.EipAddress.IpAddress) > 0 {
|
||||
return self.host.zone.region.GetEip(self.EipAddress.AllocationId)
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SInstance) GetVcpuCount() int8 {
|
||||
return self.Cpu
|
||||
}
|
||||
|
||||
func (self *SInstance) GetVmemSizeMB() int {
|
||||
return self.Memory
|
||||
}
|
||||
|
||||
func (self *SInstance) GetBootOrder() string {
|
||||
return "dcn"
|
||||
}
|
||||
|
||||
func (self *SInstance) GetVga() string {
|
||||
return "std"
|
||||
}
|
||||
|
||||
func (self *SInstance) GetVdi() string {
|
||||
return "vnc"
|
||||
}
|
||||
|
||||
func (self *SInstance) GetOSType() string {
|
||||
return osprofile.NormalizeOSType(self.OSType)
|
||||
}
|
||||
|
||||
func (self *SInstance) GetOSName() string {
|
||||
return self.OSName
|
||||
}
|
||||
|
||||
func (self *SInstance) GetBios() string {
|
||||
return "BIOS"
|
||||
}
|
||||
|
||||
func (self *SInstance) GetMachine() string {
|
||||
return "pc"
|
||||
}
|
||||
|
||||
func (self *SInstance) SyncSecurityGroup(secgroupId string, name string, rules []secrules.SecurityRule) error {
|
||||
if vpc, err := self.getVpc(); err != nil {
|
||||
return err
|
||||
} else if len(secgroupId) == 0 {
|
||||
for index, secgrpId := range self.SecurityGroupIds.SecurityGroupId {
|
||||
if err := vpc.revokeSecurityGroup(secgrpId, self.InstanceId, index == 0); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else if secgrpId, err := vpc.SyncSecurityGroup(secgroupId, name, rules); err != nil {
|
||||
return err
|
||||
} else if err := vpc.assignSecurityGroup(secgrpId, self.InstanceId); err != nil {
|
||||
return err
|
||||
} else {
|
||||
for _, secgroupId := range self.SecurityGroupIds.SecurityGroupId {
|
||||
if secgroupId != secgrpId {
|
||||
if err := vpc.revokeSecurityGroup(secgroupId, self.InstanceId, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
self.SecurityGroupIds.SecurityGroupId = []string{secgrpId}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SInstance) GetHypervisor() string {
|
||||
return models.HYPERVISOR_AWS
|
||||
}
|
||||
|
||||
func (self *SInstance) StartVM() error {
|
||||
timeout := 300 * time.Second
|
||||
interval := 15 * time.Second
|
||||
|
||||
startTime := time.Now()
|
||||
for time.Now().Sub(startTime) < timeout {
|
||||
err := self.Refresh()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Debugf("status %s expect %s", self.GetStatus(), models.VM_RUNNING)
|
||||
if self.GetStatus() == models.VM_RUNNING {
|
||||
return nil
|
||||
} else if self.GetStatus() == models.VM_READY {
|
||||
err := self.host.zone.region.StartVM(self.InstanceId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
time.Sleep(interval)
|
||||
}
|
||||
return cloudprovider.ErrTimeout
|
||||
}
|
||||
|
||||
func (self *SInstance) StopVM(isForce bool) error {
|
||||
err := self.host.zone.region.StopVM(self.InstanceId, isForce)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return cloudprovider.WaitStatus(self, models.VM_READY, 10*time.Second, 300*time.Second) // 5mintues
|
||||
}
|
||||
|
||||
func (self *SInstance) DeleteVM() error {
|
||||
for {
|
||||
err := self.host.zone.region.DeleteVM(self.InstanceId)
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return cloudprovider.WaitDeleted(self, 10*time.Second, 300*time.Second) // 5minutes
|
||||
|
||||
}
|
||||
|
||||
func (self *SInstance) UpdateVM(name string) error {
|
||||
return self.host.zone.region.UpdateVM(self.InstanceId, name)
|
||||
}
|
||||
|
||||
func (self *SInstance) RebuildRoot(imageId string, passwd string, publicKey string, sysSizeGB int) (string, error) {
|
||||
if len(publicKey) > 0 || len(passwd) > 0 {
|
||||
return "", fmt.Errorf("aws rebuild root not support specific publickey/password")
|
||||
}
|
||||
|
||||
diskId, err := self.host.zone.region.ReplaceSystemDisk(self.InstanceId, imageId, sysSizeGB)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return diskId, nil
|
||||
}
|
||||
|
||||
func (self *SInstance) DeployVM(name string, password string, publicKey string, deleteKeypair bool, description string) error {
|
||||
return self.host.zone.region.DeployVM(self.InstanceId, name, password, publicKey, deleteKeypair, description)
|
||||
}
|
||||
|
||||
func (self *SInstance) ChangeConfig(instanceId string, ncpu int, vmem int) error {
|
||||
return self.host.zone.region.ChangeVMConfig(self.ZoneId, self.InstanceId, ncpu, vmem, nil)
|
||||
}
|
||||
|
||||
func (self *SInstance) GetVNCInfo() (jsonutils.JSONObject, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (self *SInstance) AttachDisk(diskId string) error {
|
||||
// todo:bugfix . self.DeviceNames => self.GetDeviceNames()
|
||||
name, err := NextDeviceName(self.DeviceNames)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return self.host.zone.region.AttachDisk(self.InstanceId, diskId, name)
|
||||
}
|
||||
|
||||
func (self *SInstance) DetachDisk(diskId string) error {
|
||||
return self.host.zone.region.DetachDisk(self.InstanceId, diskId)
|
||||
}
|
||||
|
||||
func (self *SInstance) getVpc() (*SVpc, error) {
|
||||
return self.host.zone.region.getVpc(self.VpcAttributes.VpcId)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetInstances(zoneId string, ids []string, offset int, limit int) ([]SInstance, int, error) {
|
||||
params := &ec2.DescribeInstancesInput{}
|
||||
filters := make([]*ec2.Filter, 0)
|
||||
if len(zoneId) > 0 {
|
||||
filters = AppendSingleValueFilter(filters, "availability-zone", zoneId)
|
||||
}
|
||||
|
||||
if len(ids) > 0 {
|
||||
params = params.SetInstanceIds(ConvertedList(ids))
|
||||
}
|
||||
|
||||
if len(filters) > 0 {
|
||||
params = params.SetFilters(filters)
|
||||
}
|
||||
|
||||
log.Debugf("GetInstances with params: %s", params.String())
|
||||
res, err := self.ec2Client.DescribeInstances(params)
|
||||
if err != nil {
|
||||
log.Errorf("GetInstances fail %s", err)
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
instances := []SInstance{}
|
||||
for _, reservation := range res.Reservations {
|
||||
for _, instance := range reservation.Instances {
|
||||
log.Debugf("GetInstances %s", instance.String())
|
||||
if err := FillZero(instance); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
instanceType, err := self.GetInstanceType(*instance.InstanceType)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
tagspec := TagSpec{}
|
||||
tagspec.LoadingEc2Tags(instance.Tags)
|
||||
|
||||
disks := []string{}
|
||||
devicenames := []string{}
|
||||
for _, d := range instance.BlockDeviceMappings {
|
||||
if d.Ebs != nil && d.Ebs.VolumeId != nil {
|
||||
disks = append(disks, *d.Ebs.VolumeId)
|
||||
devicenames = append(devicenames, *d.DeviceName)
|
||||
}
|
||||
}
|
||||
|
||||
var secgroups SSecurityGroupIds
|
||||
for _, s := range instance.SecurityGroups {
|
||||
if s.GroupId != nil {
|
||||
secgroups.SecurityGroupId = append(secgroups.SecurityGroupId, *s.GroupId)
|
||||
}
|
||||
}
|
||||
|
||||
var networkInterfaces SNetworkInterfaces
|
||||
for _, n := range instance.NetworkInterfaces {
|
||||
i := SNetworkInterface{
|
||||
MacAddress: *n.MacAddress,
|
||||
NetworkInterfaceId: *n.NetworkInterfaceId,
|
||||
PrimaryIpAddress: *n.PrivateIpAddress,
|
||||
}
|
||||
networkInterfaces.NetworkInterface = append(networkInterfaces.NetworkInterface, i)
|
||||
}
|
||||
|
||||
var vpcattr SVpcAttributes
|
||||
vpcattr.VpcId = *instance.VpcId
|
||||
vpcattr.PrivateIpAddress = SIpAddress{[]string{*instance.PrivateIpAddress}}
|
||||
vpcattr.NetworkId = *instance.SubnetId
|
||||
|
||||
var productCodes []string
|
||||
for _, p := range instance.ProductCodes {
|
||||
productCodes = append(productCodes, *p.ProductCodeId)
|
||||
}
|
||||
|
||||
sinstance := SInstance{
|
||||
RegionId: self.RegionId,
|
||||
ZoneId: *instance.Placement.AvailabilityZone,
|
||||
InstanceId: *instance.InstanceId,
|
||||
ImageId: *instance.ImageId,
|
||||
InstanceType: *instance.InstanceType,
|
||||
Cpu: int8(*instance.CpuOptions.CoreCount),
|
||||
Memory: instanceType.memoryMB(),
|
||||
IoOptimized: *instance.EbsOptimized,
|
||||
KeyPairName: *instance.KeyName,
|
||||
CreationTime: *instance.LaunchTime,
|
||||
PublicDNSName: *instance.PublicDnsName,
|
||||
RootDeviceName: *instance.RootDeviceName,
|
||||
Status: *instance.State.Name,
|
||||
InnerIpAddress: SIpAddress{[]string{*instance.PrivateIpAddress}},
|
||||
PublicIpAddress: SIpAddress{[]string{*instance.PublicIpAddress}},
|
||||
InstanceName: tagspec.GetNameTag(),
|
||||
Description: tagspec.GetDescTag(),
|
||||
Disks: disks,
|
||||
DeviceNames: devicenames,
|
||||
SecurityGroupIds: secgroups,
|
||||
NetworkInterfaces: networkInterfaces,
|
||||
VpcAttributes: vpcattr,
|
||||
ProductCodes: productCodes,
|
||||
// OSName todo: 通过关联的image获取 OS Name
|
||||
// ExpiredTime:
|
||||
// EipAddress:
|
||||
// VlanId:
|
||||
// OSType:
|
||||
}
|
||||
|
||||
instances = append(instances, sinstance)
|
||||
}
|
||||
}
|
||||
|
||||
return instances, len(instances), nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetInstance(instanceId string) (*SInstance, error) {
|
||||
instances, _, err := self.GetInstances("", []string{instanceId}, 0, 1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(instances) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return &instances[0], nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetInstanceIdByImageId(imageId string) (string, error) {
|
||||
params := &ec2.DescribeInstancesInput{}
|
||||
filters := []*ec2.Filter{}
|
||||
filters = AppendSingleValueFilter(filters, "image-id", imageId)
|
||||
params.SetFilters(filters)
|
||||
ret, err := self.ec2Client.DescribeInstances(params)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
for _, item := range ret.Reservations {
|
||||
for _, instance := range item.Instances {
|
||||
return *instance.InstanceId, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("instance launch with image %s not found", imageId)
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateInstance(name string, imageId string, instanceType string, SubnetId string, securityGroupId string,
|
||||
zoneId string, desc string, disks []SDisk, ipAddr string,
|
||||
keypair string) (string, error) {
|
||||
var count int64 = 1
|
||||
// disk
|
||||
blockDevices := []*ec2.BlockDeviceMapping{}
|
||||
for i, disk := range disks {
|
||||
if i == 0 {
|
||||
var size int64
|
||||
size = int64(disk.Size)
|
||||
ebs := &ec2.EbsBlockDevice{
|
||||
DeleteOnTermination: &disk.DeleteWithInstance,
|
||||
// The st1 volume type cannot be used for boot volumes. Please use a supported boot volume type: standard,io1,gp2.
|
||||
// the encrypted flag cannot be specified since device /dev/sda1 has a snapshot specified.
|
||||
// Encrypted: &disk.Encrypted,
|
||||
VolumeSize: &size,
|
||||
VolumeType: &disk.Category,
|
||||
}
|
||||
|
||||
// todo: 这里是镜像绑定的deviceName
|
||||
divceName := fmt.Sprintf("/dev/sda1")
|
||||
blockDevice := &ec2.BlockDeviceMapping{
|
||||
DeviceName: &divceName,
|
||||
Ebs: ebs,
|
||||
}
|
||||
|
||||
blockDevices = append(blockDevices, blockDevice)
|
||||
} else {
|
||||
var size int64
|
||||
size = int64(disk.Size)
|
||||
ebs := &ec2.EbsBlockDevice{
|
||||
DeleteOnTermination: &disk.DeleteWithInstance,
|
||||
Encrypted: &disk.Encrypted,
|
||||
VolumeSize: &size,
|
||||
VolumeType: &disk.Category,
|
||||
}
|
||||
// todo: generator device name
|
||||
divceName := fmt.Sprintf("/dev/sd%s", string(98+i))
|
||||
blockDevice := &ec2.BlockDeviceMapping{
|
||||
DeviceName: &divceName,
|
||||
Ebs: ebs,
|
||||
}
|
||||
|
||||
blockDevices = append(blockDevices, blockDevice)
|
||||
}
|
||||
}
|
||||
// tags
|
||||
tags := TagSpec{ResourceType: "instance"}
|
||||
tags.SetNameTag(name)
|
||||
tags.SetDescTag(desc)
|
||||
ec2TagSpec, err := tags.GetTagSpecifications()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
params := ec2.RunInstancesInput{
|
||||
ImageId: &imageId,
|
||||
InstanceType: &instanceType,
|
||||
MaxCount: &count,
|
||||
MinCount: &count,
|
||||
SubnetId: &SubnetId,
|
||||
PrivateIpAddress: &ipAddr,
|
||||
BlockDeviceMappings: blockDevices,
|
||||
KeyName: &keypair,
|
||||
Placement: &ec2.Placement{AvailabilityZone: &zoneId},
|
||||
SecurityGroupIds: []*string{&securityGroupId},
|
||||
TagSpecifications: []*ec2.TagSpecification{ec2TagSpec},
|
||||
}
|
||||
res, err := self.ec2Client.RunInstances(¶ms)
|
||||
if err != nil {
|
||||
log.Errorf("CreateInstance fail %s", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(res.Instances) == 1 {
|
||||
return *res.Instances[0].InstanceId, nil
|
||||
} else {
|
||||
msg := fmt.Sprintf("CreateInstance fail: %s instance created. ", len(res.Instances))
|
||||
log.Errorf(msg)
|
||||
return "", fmt.Errorf(msg)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) GetInstanceStatus(instanceId string) (string, error) {
|
||||
instance, err := self.GetInstance(instanceId)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return instance.Status, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) instanceStatusChecking(instanceId, status string) error {
|
||||
remoteStatus, err := self.GetInstanceStatus(instanceId)
|
||||
if err != nil {
|
||||
log.Errorf("Fail to get instance status on StartVM: %s", err)
|
||||
return err
|
||||
}
|
||||
if status != remoteStatus {
|
||||
log.Errorf("StartVM: vm status is %s expect %s", remoteStatus, status)
|
||||
return cloudprovider.ErrInvalidStatus
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) StartVM(instanceId string) error {
|
||||
if err := self.instanceStatusChecking(instanceId, InstanceStatusStopped); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
params := &ec2.StartInstancesInput{}
|
||||
params.SetInstanceIds([]*string{&instanceId})
|
||||
_, err := self.ec2Client.StartInstances(params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SRegion) StopVM(instanceId string, isForce bool) error {
|
||||
if err := self.instanceStatusChecking(instanceId, InstanceStatusRunning); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
params := &ec2.StopInstancesInput{}
|
||||
params.SetInstanceIds([]*string{&instanceId})
|
||||
_, err := self.ec2Client.StopInstances(params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SRegion) DeleteVM(instanceId string) error {
|
||||
if err := self.instanceStatusChecking(instanceId, InstanceStatusStopped); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
params := &ec2.TerminateInstancesInput{}
|
||||
params.SetInstanceIds([]*string{&instanceId})
|
||||
_, err := self.ec2Client.TerminateInstances(params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SRegion) DeployVM(instanceId string, name string, password string, keypairName string, deleteKeypair bool, description string) error {
|
||||
params := &ec2.CreateTagsInput{}
|
||||
params.SetResources([]*string{&instanceId})
|
||||
tagspec := TagSpec{ResourceType: "instance"}
|
||||
|
||||
if len(keypairName) > 0 {
|
||||
return fmt.Errorf("aws not support reset publickey")
|
||||
}
|
||||
|
||||
if len(password) > 0 {
|
||||
return fmt.Errorf("aws not support set password, use publickey instead")
|
||||
}
|
||||
|
||||
if deleteKeypair {
|
||||
return fmt.Errorf("aws not support delete publickey")
|
||||
}
|
||||
|
||||
if len(name) > 0 {
|
||||
tagspec.SetNameTag(name)
|
||||
}
|
||||
|
||||
if len(description) > 0 {
|
||||
tagspec.SetDescTag(description)
|
||||
}
|
||||
|
||||
ec2Tag, _ := tagspec.GetTagSpecifications()
|
||||
if len(ec2Tag.Tags) > 0 {
|
||||
params.SetTags(ec2Tag.Tags)
|
||||
_, err := self.ec2Client.CreateTags(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
log.Debugf("no changes")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) UpdateVM(instanceId string, hostname string) error {
|
||||
// https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/set-hostname.html
|
||||
return fmt.Errorf("aws not support change hostname.")
|
||||
}
|
||||
|
||||
func (self *SRegion) ReplaceSystemDisk(instanceId string, imageId string, sysDiskSizeGB int) (string, error) {
|
||||
instance, err := self.GetInstance(instanceId)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
disks, _, err := self.GetDisks(instanceId, instance.ZoneId, "", nil, 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var rootDisk *SDisk
|
||||
for _, disk := range disks {
|
||||
if disk.Type == models.DISK_TYPE_SYS {
|
||||
rootDisk = &disk
|
||||
}
|
||||
}
|
||||
|
||||
if rootDisk == nil {
|
||||
return "", fmt.Errorf("can not find root disk of instance %s", instanceId)
|
||||
}
|
||||
|
||||
image, err := self.GetImage(imageId)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
diskId, err := self.CreateDisk(instance.ZoneId, rootDisk.Category, rootDisk.GetName(), sysDiskSizeGB, image.RootDevice.SnapshotId, "")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
self.ec2Client.WaitUntilVolumeAvailable(&ec2.DescribeVolumesInput{VolumeIds: []*string{&diskId}})
|
||||
// todo: 检查instance状态
|
||||
err = instance.DetachDisk(rootDisk.DiskId)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
self.ec2Client.WaitUntilInstanceStopped(&ec2.DescribeInstancesInput{InstanceIds: []*string{&instanceId}})
|
||||
err = instance.AttachDisk(diskId)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
self.ec2Client.WaitUntilInstanceStopped(&ec2.DescribeInstancesInput{InstanceIds: []*string{&instanceId}})
|
||||
return diskId, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) ChangeVMConfig(zoneId string, instanceId string, ncpu int, vmem int, disks []*SDisk) error {
|
||||
params := &ec2.ModifyInstanceAttributeInput{}
|
||||
params.SetInstanceId(instanceId)
|
||||
instanceTypes, err := self.GetMatchInstanceTypes(ncpu, vmem, 0, zoneId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, instancetype := range instanceTypes {
|
||||
t := &ec2.AttributeValue{Value: &instancetype.InstanceTypeId}
|
||||
params.SetInstanceType(t)
|
||||
|
||||
_, err := self.ec2Client.ModifyInstanceAttribute(params)
|
||||
if err != nil {
|
||||
log.Errorf("Failed for %s: %s", instancetype.InstanceTypeId, err)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("Failed to change vm config, specification not supported")
|
||||
}
|
||||
|
||||
func (self *SRegion) DetachDisk(instanceId string, diskId string) error {
|
||||
params := &ec2.DetachVolumeInput{}
|
||||
params.SetInstanceId(instanceId)
|
||||
params.SetVolumeId(diskId)
|
||||
|
||||
_, err := self.ec2Client.DetachVolume(params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SRegion) AttachDisk(instanceId string, diskId string, deviceName string) error {
|
||||
params := &ec2.AttachVolumeInput{}
|
||||
params.SetInstanceId(instanceId)
|
||||
params.SetVolumeId(diskId)
|
||||
params.SetDevice(deviceName)
|
||||
|
||||
_, err := self.ec2Client.AttachVolume(params)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
)
|
||||
|
||||
type SInstanceNic struct {
|
||||
instance *SInstance
|
||||
ipAddr string
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) GetIP() string {
|
||||
return self.ipAddr
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) GetMAC() string {
|
||||
ip, _ := netutils.NewIPV4Addr(self.ipAddr)
|
||||
return ip.ToMac("00:16:")
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) GetDriver() string {
|
||||
return "virtio"
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) GetINetwork() cloudprovider.ICloudNetwork {
|
||||
networkId := self.instance.VpcAttributes.NetworkId
|
||||
wires, err := self.instance.host.GetIWires()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
for i := 0; i < len(wires); i += 1 {
|
||||
wire := wires[i].(*SWire)
|
||||
net := wire.getNetworkById(networkId)
|
||||
if net != nil {
|
||||
return net
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
)
|
||||
|
||||
type Cpu struct {
|
||||
Cores int `json:"cores"`
|
||||
Units string `json:"units"`
|
||||
}
|
||||
|
||||
type CpuCredits struct {
|
||||
OptimizationSupported bool `json:"optimizationSupported"`
|
||||
}
|
||||
|
||||
type ProcessorFeatures struct {
|
||||
AESNI bool `json:"AES-NI"`
|
||||
AVX bool `json:"AVX"`
|
||||
Turbo bool `json:"Turbo"`
|
||||
}
|
||||
|
||||
type SInstanceType struct {
|
||||
Architectures []string `json:"architectures"`
|
||||
Cpu Cpu `json:"cpu"`
|
||||
CpuCredits CpuCredits `json:"cpuCredits"`
|
||||
Description string `json:"description"`
|
||||
EbsEncryptionSupported bool `json:"ebsEncryptionSupported"`
|
||||
EbsOnly bool `json:"ebsOnly"`
|
||||
Family string `json:"family"`
|
||||
FreeTierEligible bool `json:"freeTierEligible"`
|
||||
Ipv6Support bool `json:"ipv6Support"`
|
||||
Memory float32 `json:"memory"`
|
||||
NetworkPerformance string `json:"networkPerformance"`
|
||||
PhysicalProcessor string `json:"physicalProcessor"`
|
||||
ProcessorFeatures ProcessorFeatures `json:"processorFeatures"`
|
||||
ProcessorSpeed float32 `json:"processorSpeed"`
|
||||
SpotSupported bool `json:"spotSupported"`
|
||||
InstanceTypeId string `json:"typeName"`
|
||||
VirtualizationTypes []string `json:"virtualizationTypes"`
|
||||
Vpc bool `json:"vpc"`
|
||||
VpcOnly bool `json:"vpcOnly"`
|
||||
Windows bool `json:"windows"`
|
||||
}
|
||||
|
||||
func (self *SInstanceType) memoryMB() int {
|
||||
return int(self.Memory * 1024)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetInstanceTypes() ([]SInstanceType, error) {
|
||||
if self.instanceTypes == nil {
|
||||
var GlobalInstanceTyes []SInstanceType
|
||||
instanceTypes, err := ioutil.ReadFile(options.Options.DefaultAwsInstanceTypeFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(instanceTypes), &GlobalInstanceTyes)
|
||||
if err != nil {
|
||||
log.Errorf("GetInstanceTypes %s", err)
|
||||
return nil, err
|
||||
}
|
||||
return GlobalInstanceTyes, err
|
||||
} else {
|
||||
return self.instanceTypes, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) GetInstanceType(instanceTypeId string) (*SInstanceType, error) {
|
||||
ret, err := self.GetInstanceTypes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, item := range ret {
|
||||
if item.InstanceTypeId == instanceTypeId {
|
||||
return &item, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("instancetype %s not found", instanceTypeId)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetMatchInstanceTypes(cpu int, memMB int, gpu int, zoneId string) ([]SInstanceType, error) {
|
||||
types, err := self.GetInstanceTypes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 实例类型顺序: 微型实例 -> 通用型 -> 计算优化型 ...
|
||||
// todo:部分实例类型 需要启用ena才能正常启动。需要过滤掉。
|
||||
// https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/enhanced-networking-ena.html
|
||||
ret := []SInstanceType{}
|
||||
for _, t := range types {
|
||||
// cpu & mem & disk & ena 都匹配才行
|
||||
if t.Cpu.Cores == cpu && t.memoryMB() == memMB {
|
||||
ret = append(ret, t)
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/aokoli/goutils"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"strconv"
|
||||
"time"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
type SKeypair struct {
|
||||
KeyPairFingerPrint string
|
||||
KeyPairName string
|
||||
}
|
||||
|
||||
func (self *SRegion) GetKeypairs(finger string, name string, offset int, limit int) ([]SKeypair, int, error) {
|
||||
ret, err := self.ec2Client.DescribeKeyPairs(&ec2.DescribeKeyPairsInput{})
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
keypairs := []SKeypair{}
|
||||
for _, item := range ret.KeyPairs {
|
||||
if err := FillZero(item); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
keypairs = append(keypairs, SKeypair{*item.KeyFingerprint, *item.KeyName})
|
||||
}
|
||||
|
||||
return keypairs, len(keypairs), nil
|
||||
}
|
||||
|
||||
func (self *SRegion) ImportKeypair(name string, pubKey string) (*SKeypair, error) {
|
||||
params := &ec2.ImportKeyPairInput{}
|
||||
params.SetKeyName(name)
|
||||
params.SetPublicKeyMaterial([]byte(pubKey))
|
||||
ret, err := self.ec2Client.ImportKeyPair(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return &SKeypair{StrVal(ret.KeyFingerprint), StrVal(ret.KeyName)}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) AttachKeypair(instanceId string, keypairName string) error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (self *SRegion) DetachKeyPair(instanceId string, keypairName string) error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (self *SRegion) lookUpAwsKeypair(publicKey string) (string, error) {
|
||||
pk, _, _, _, err := ssh.ParseAuthorizedKey([]byte(publicKey))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("publicKey error %s", err)
|
||||
}
|
||||
|
||||
fingerprint := ssh.FingerprintLegacyMD5(pk)
|
||||
ks, total, err := self.GetKeypairs(fingerprint, "*", 0, 1)
|
||||
if total < 1 {
|
||||
return "", fmt.Errorf("keypair not found %s", err)
|
||||
} else {
|
||||
return ks[0].KeyPairName, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) importAwsKeypair(publicKey string) (string, error) {
|
||||
prefix, e := goutils.RandomAlphabetic(6)
|
||||
if e != nil {
|
||||
return "", fmt.Errorf("publicKey error %s", e)
|
||||
}
|
||||
|
||||
name := prefix + strconv.FormatInt(time.Now().Unix(), 10)
|
||||
if k, e := self.ImportKeypair(name, publicKey); e != nil {
|
||||
return "", fmt.Errorf("keypair import error %s", e)
|
||||
} else {
|
||||
return k.KeyPairName, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) syncKeypair(publicKey string) (string, error) {
|
||||
name, e := self.lookUpAwsKeypair(publicKey)
|
||||
if e == nil {
|
||||
return name, nil
|
||||
}
|
||||
return self.importAwsKeypair(publicKey)
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"strings"
|
||||
"time"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
)
|
||||
|
||||
type SNetwork struct {
|
||||
wire *SWire
|
||||
|
||||
AvailableIpAddressCount int
|
||||
CidrBlock string
|
||||
CreationTime time.Time
|
||||
Description string
|
||||
IsDefault bool
|
||||
Status string
|
||||
NetworkId string
|
||||
NetworkName string
|
||||
VpcId string
|
||||
ZoneId string
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetId() string {
|
||||
return self.NetworkId
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetName() string {
|
||||
return self.NetworkName
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetGlobalId() string {
|
||||
return self.NetworkId
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetStatus() string {
|
||||
return strings.ToLower(self.Status)
|
||||
}
|
||||
|
||||
func (self *SNetwork) Refresh() error {
|
||||
log.Debugf("network refresh %s", self.NetworkId)
|
||||
new, err := self.wire.zone.region.getNetwork(self.NetworkId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(self, new)
|
||||
}
|
||||
|
||||
func (self *SNetwork) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetMetadata() *jsonutils.JSONDict {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetIWire() cloudprovider.ICloudWire {
|
||||
return self.wire
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetIpStart() string {
|
||||
pref, _ := netutils.NewIPV4Prefix(self.CidrBlock)
|
||||
startIp := pref.Address.NetAddr(pref.MaskLen) // 0
|
||||
startIp = startIp.StepUp() // 1
|
||||
return startIp.String()
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetIpEnd() string {
|
||||
pref, _ := netutils.NewIPV4Prefix(self.CidrBlock)
|
||||
endIp := pref.Address.BroadcastAddr(pref.MaskLen) // 255
|
||||
endIp = endIp.StepDown() // 254
|
||||
endIp = endIp.StepDown() // 253
|
||||
endIp = endIp.StepDown() // 252
|
||||
return endIp.String()
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetIpMask() int8 {
|
||||
pref, _ := netutils.NewIPV4Prefix(self.CidrBlock)
|
||||
return pref.MaskLen
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetGateway() string {
|
||||
pref, _ := netutils.NewIPV4Prefix(self.CidrBlock)
|
||||
endIp := pref.Address.BroadcastAddr(pref.MaskLen) // 255
|
||||
endIp = endIp.StepDown() // 254
|
||||
return endIp.String()
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetServerType() string {
|
||||
return models.SERVER_TYPE_GUEST
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetIsPublic() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SNetwork) Delete() error {
|
||||
return self.wire.zone.region.deleteNetwork(self.NetworkId)
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetAllocTimeoutSeconds() int {
|
||||
return 120 // 2 minutes
|
||||
}
|
||||
|
||||
func (self *SRegion) createNetwork(zoneId string, vpcId string, name string, cidr string, desc string) (string, error) {
|
||||
params := &ec2.CreateSubnetInput{}
|
||||
params.SetAvailabilityZone(zoneId)
|
||||
params.SetVpcId(vpcId)
|
||||
params.SetCidrBlock(cidr)
|
||||
|
||||
ret, err := self.ec2Client.CreateSubnet(params)
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
return *ret.Subnet.SubnetId, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) getNetwork(networkId string) (*SNetwork, error) {
|
||||
networks, total, err := self.GetNetwroks([]string{networkId}, "", 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if total != 1 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return &networks[0], nil
|
||||
}
|
||||
|
||||
func (self *SRegion) deleteNetwork(networkId string) error {
|
||||
params := &ec2.DeleteSubnetInput{}
|
||||
params.SetSubnetId(networkId)
|
||||
_, err := self.ec2Client.DeleteSubnet(params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SRegion) GetNetwroks(ids []string, vpcId string, limit int, offset int) ([]SNetwork, int, error) {
|
||||
params := &ec2.DescribeSubnetsInput{}
|
||||
if len(ids) > 0 {
|
||||
_ids := make([]*string, len(ids))
|
||||
for _, id := range ids {
|
||||
_ids = append(_ids, &id)
|
||||
}
|
||||
params.SetSubnetIds(_ids)
|
||||
}
|
||||
|
||||
if len(vpcId) > 0 {
|
||||
filters := make([]*ec2.Filter, 1)
|
||||
vpcFilter := &ec2.Filter{}
|
||||
vpcFilter.SetName("vpc-id")
|
||||
vpcFilter.SetValues([]*string{&vpcId})
|
||||
filters = append(filters, vpcFilter)
|
||||
params.SetFilters(filters)
|
||||
}
|
||||
|
||||
ret, err := self.ec2Client.DescribeSubnets(params)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
subnets := []SNetwork{}
|
||||
for _, item := range ret.Subnets {
|
||||
if err := FillZero(item); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
subnet := SNetwork{}
|
||||
subnet.CidrBlock = *item.CidrBlock
|
||||
subnet.VpcId = *item.VpcId
|
||||
subnet.Status = *item.State
|
||||
subnet.ZoneId = *item.AvailabilityZone
|
||||
subnet.IsDefault = *item.DefaultForAz
|
||||
subnet.NetworkId = *item.SubnetId
|
||||
subnet.NetworkName = *item.SubnetId
|
||||
subnets = append(subnets, subnet)
|
||||
}
|
||||
return subnets, len(subnets), nil
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/util/aws"
|
||||
)
|
||||
|
||||
type SAwsProviderFactory struct {
|
||||
}
|
||||
|
||||
func (self *SAwsProviderFactory) GetId() string {
|
||||
return aws.CLOUD_PROVIDER_AWS
|
||||
}
|
||||
|
||||
func (self *SAwsProviderFactory) GetProvider(providerId, providerName, url, account, secret string) (cloudprovider.ICloudProvider, error) {
|
||||
client, err := aws.NewAwsClient(providerId, providerName, url, account, secret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &SAwsProvider{client: client}, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
factory := SAwsProviderFactory{}
|
||||
cloudprovider.RegisterFactory(&factory)
|
||||
}
|
||||
|
||||
type SAwsProvider struct {
|
||||
client *aws.SAwsClient
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) GetSubAccounts() ([]cloudprovider.SSubAccount, error) {
|
||||
return self.client.GetSubAccounts()
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) GetId() string {
|
||||
return aws.CLOUD_PROVIDER_AWS
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) GetName() string {
|
||||
return aws.CLOUD_PROVIDER_AWS_CN
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) GetIRegions() []cloudprovider.ICloudRegion {
|
||||
return self.client.GetIRegions()
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) GetSysInfo() (jsonutils.JSONObject, error) {
|
||||
regions := self.client.GetIRegions()
|
||||
info := jsonutils.NewDict()
|
||||
info.Add(jsonutils.NewInt(int64(len(regions))), "region_count")
|
||||
info.Add(jsonutils.NewString(aws.AWS_API_VERSION), "api_version")
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) IsPublicCloud() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) GetIRegionById(id string) (cloudprovider.ICloudRegion, error) {
|
||||
return self.client.GetIRegionById(id)
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
|
||||
return self.client.GetIHostById(id)
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) {
|
||||
return self.client.GetIVpcById(id)
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
|
||||
return self.client.GetIStorageById(id)
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) GetIStoragecacheById(id string) (cloudprovider.ICloudStoragecache, error) {
|
||||
return self.client.GetIStoragecacheById(id)
|
||||
}
|
||||
|
||||
func (self *SAwsProvider) GetBalance() (float64, error) {
|
||||
balance, err := self.client.QueryAccountBalance()
|
||||
if err != nil {
|
||||
return 0.0, err
|
||||
}
|
||||
return balance.AvailableAmount, nil
|
||||
}
|
||||
@@ -0,0 +1,371 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
sdk "github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/aws/aws-sdk-go/service/iam"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
type SRegion struct {
|
||||
client *SAwsClient
|
||||
ec2Client *ec2.EC2
|
||||
iamClient *iam.IAM
|
||||
s3Client *s3.S3
|
||||
|
||||
izones []cloudprovider.ICloudZone
|
||||
ivpcs []cloudprovider.ICloudVpc
|
||||
|
||||
storageCache *SStoragecache
|
||||
instanceTypes []SInstanceType
|
||||
|
||||
RegionEndpoint string
|
||||
RegionId string // 这里为保持一致沿用阿里云RegionId的叫法, 与AWS RegionName字段对应
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/* 请不要使用这个client(AWS_DEFAULT_REGION)跨region查信息.有可能导致查询返回的信息为空。比如DescribeAvailabilityZones*/
|
||||
func (self *SRegion) GetClient() *SAwsClient {
|
||||
return self.client
|
||||
}
|
||||
|
||||
func (self *SRegion) getEc2Client() (*ec2.EC2, error) {
|
||||
if self.ec2Client == nil {
|
||||
s, err := session.NewSession(&sdk.Config{
|
||||
Region: sdk.String(self.RegionId),
|
||||
Credentials: credentials.NewStaticCredentials(self.client.accessKey, self.client.secret, ""),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
self.ec2Client = ec2.New(s)
|
||||
return self.ec2Client, nil
|
||||
}
|
||||
|
||||
return self.ec2Client, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) getIamClient() (*iam.IAM, error) {
|
||||
if self.iamClient == nil {
|
||||
s, err := session.NewSession(&sdk.Config{
|
||||
Region: sdk.String(self.RegionId),
|
||||
Credentials: credentials.NewStaticCredentials(self.client.accessKey, self.client.secret, ""),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
self.iamClient = iam.New(s)
|
||||
}
|
||||
|
||||
return self.iamClient, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) getS3Client() (*s3.S3, error) {
|
||||
if self.s3Client == nil {
|
||||
s, err := session.NewSession(&sdk.Config{
|
||||
Region: sdk.String(self.RegionId),
|
||||
Credentials: credentials.NewStaticCredentials(self.client.accessKey, self.client.secret, ""),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
self.s3Client = s3.New(s)
|
||||
}
|
||||
|
||||
return self.s3Client, nil
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
func (self *SRegion) fetchZones() error {
|
||||
// todo: 这里将过滤出指定region下全部的zones。是否只过滤出可用的zone即可? The state of the Availability Zone (available | information | impaired | unavailable)
|
||||
zones, err := self.ec2Client.DescribeAvailabilityZones(&ec2.DescribeAvailabilityZonesInput{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = FillZero(zones)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.izones = make([]cloudprovider.ICloudZone, 0)
|
||||
for _, zone := range zones.AvailabilityZones {
|
||||
self.izones = append(self.izones, &SZone{ZoneId: *zone.ZoneName, State: *zone.State, LocalName: *zone.ZoneName, region: self})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) fetchIVpcs() error {
|
||||
vpcs, err := self.ec2Client.DescribeVpcs(&ec2.DescribeVpcsInput{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.ivpcs = make([]cloudprovider.ICloudVpc, 0)
|
||||
for _, vpc := range vpcs.Vpcs {
|
||||
tags := make(map[string]string, 0)
|
||||
for _, tag := range vpc.Tags {
|
||||
tags[*tag.Key] = *tag.Value
|
||||
}
|
||||
|
||||
self.ivpcs = append(self.ivpcs, &SVpc{region: self,
|
||||
CidrBlock: *vpc.CidrBlock,
|
||||
Tags: tags,
|
||||
IsDefault: *vpc.IsDefault,
|
||||
RegionId: self.RegionId,
|
||||
Status: *vpc.State,
|
||||
VpcId: *vpc.VpcId,
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) fetchInfrastructure() error {
|
||||
if _, err := self.getEc2Client(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := self.fetchZones(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := self.fetchIVpcs(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := 0; i < len(self.ivpcs); i += 1 {
|
||||
for j := 0; j < len(self.izones); j += 1 {
|
||||
zone := self.izones[j].(*SZone)
|
||||
vpc := self.ivpcs[i].(*SVpc)
|
||||
wire := SWire{zone: zone, vpc: vpc}
|
||||
zone.addWire(&wire)
|
||||
vpc.addWire(&wire)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetId() string {
|
||||
return self.RegionId
|
||||
}
|
||||
|
||||
func (self *SRegion) GetName() string {
|
||||
return fmt.Sprintf("%s %s", CLOUD_PROVIDER_AWS_CN, self.RegionId)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetGlobalId() string {
|
||||
return fmt.Sprintf("%s/%s", CLOUD_PROVIDER_AWS, self.RegionId)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetStatus() string {
|
||||
return models.CLOUD_REGION_STATUS_INSERVER
|
||||
}
|
||||
|
||||
func (self *SRegion) Refresh() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SRegion) GetMetadata() *jsonutils.JSONDict {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetLatitude() float32 {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
func (self *SRegion) GetLongitude() float32 {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIZones() ([]cloudprovider.ICloudZone, error) {
|
||||
if self.izones == nil {
|
||||
if err := self.fetchInfrastructure(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return self.izones, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIVpcs() ([]cloudprovider.ICloudVpc, error) {
|
||||
if self.ivpcs == nil {
|
||||
err := self.fetchInfrastructure()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return self.ivpcs, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) {
|
||||
_, err := self.getEc2Client()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
eips, total, err := self.GetEips("", 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := make([]cloudprovider.ICloudEIP, total)
|
||||
for i := 0; i < len(eips); i += 1 {
|
||||
ret[i] = &eips[i]
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
|
||||
snapshots, _, err := self.GetSnapshots("", "", "", []string{}, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := make([]cloudprovider.ICloudSnapshot, len(snapshots))
|
||||
for i := 0; i < len(snapshots); i += 1 {
|
||||
ret[i] = &snapshots[i]
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIZoneById(id string) (cloudprovider.ICloudZone, error) {
|
||||
izones, err := self.GetIZones()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, zone := range izones {
|
||||
if zone.GetGlobalId() == id {
|
||||
return zone, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) {
|
||||
ivpcs, err := self.GetIVpcs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, vpc := range ivpcs {
|
||||
if vpc.GetGlobalId() == id {
|
||||
return vpc, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
|
||||
izones, err := self.GetIZones()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(izones); i += 1 {
|
||||
ihost, err := izones[i].GetIHostById(id)
|
||||
if err == nil {
|
||||
return ihost, nil
|
||||
} else if err != cloudprovider.ErrNotFound {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
|
||||
izones, err := self.GetIZones()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(izones); i += 1 {
|
||||
istore, err := izones[i].GetIStorageById(id)
|
||||
if err == nil {
|
||||
return istore, nil
|
||||
} else if err != cloudprovider.ErrNotFound {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIStoragecacheById(id string) (cloudprovider.ICloudStoragecache, error) {
|
||||
if self.storageCache == nil {
|
||||
self.storageCache = &SStoragecache{region: self}
|
||||
}
|
||||
|
||||
if self.storageCache.GetGlobalId() == id {
|
||||
return self.storageCache, nil
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateIVpc(name string, desc string, cidr string) (cloudprovider.ICloudVpc, error) {
|
||||
vpc, err := self.ec2Client.CreateVpc(&ec2.CreateVpcInput{CidrBlock: &cidr})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = self.fetchInfrastructure()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return self.GetIVpcById(*vpc.Vpc.VpcId)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIEipById(eipId string) (cloudprovider.ICloudEIP, error) {
|
||||
eips, total, err := self.GetEips(eipId, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if total == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
if total > 1 {
|
||||
return nil, cloudprovider.ErrDuplicateId
|
||||
}
|
||||
return &eips[0], nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetProvider() string {
|
||||
return CLOUD_PROVIDER_AWS
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateInstanceSimple(name string, imgId string, cpu int, memGB int, storageType string, dataDiskSizesGB []int, networkId string, publicKey string) (*SInstance, error) {
|
||||
izones, err := self.GetIZones()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(izones); i += 1 {
|
||||
z := izones[i].(*SZone)
|
||||
log.Debugf("Search in zone %s", z.LocalName)
|
||||
net := z.getNetworkById(networkId)
|
||||
if net != nil {
|
||||
inst, err := z.getHost().CreateVM(name, imgId, 0, cpu, memGB*1024, networkId, "", "", "", storageType, dataDiskSizesGB, publicKey, "", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return inst.(*SInstance), nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("cannot find vswitch %s", networkId)
|
||||
}
|
||||
@@ -0,0 +1,444 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"sort"
|
||||
"strings"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
)
|
||||
|
||||
type Tags struct {
|
||||
Tag []Tag
|
||||
}
|
||||
|
||||
type Tag struct {
|
||||
TagKey string
|
||||
TagValue string
|
||||
}
|
||||
|
||||
type SSecurityGroup struct {
|
||||
vpc *SVpc
|
||||
|
||||
RegionId string
|
||||
VpcId string
|
||||
SecurityGroupId string
|
||||
Description string
|
||||
SecurityGroupName string
|
||||
Permissions []secrules.SecurityRule
|
||||
Tags Tags
|
||||
|
||||
// CreationTime time.Time
|
||||
// InnerAccessPolicy string
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetId() string {
|
||||
return self.SecurityGroupId
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetName() string {
|
||||
if len(self.SecurityGroupName) > 0 {
|
||||
return self.SecurityGroupName
|
||||
}
|
||||
return self.SecurityGroupId
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetGlobalId() string {
|
||||
return self.SecurityGroupId
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetStatus() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) Refresh() error {
|
||||
if new, err := self.vpc.region.GetSecurityGroupDetails(self.SecurityGroupId); err != nil {
|
||||
return err
|
||||
} else {
|
||||
return jsonutils.Update(self, new)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetMetadata() *jsonutils.JSONDict {
|
||||
if len(self.Tags.Tag) == 0 {
|
||||
return nil
|
||||
}
|
||||
data := jsonutils.NewDict()
|
||||
for _, value := range self.Tags.Tag {
|
||||
data.Add(jsonutils.NewString(value.TagValue), value.TagKey)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetDescription() string {
|
||||
return self.Description
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetRules() ([]secrules.SecurityRule, error) {
|
||||
rules := make([]secrules.SecurityRule, 0)
|
||||
if secgrp, err := self.vpc.region.GetSecurityGroupDetails(self.SecurityGroupId); err != nil {
|
||||
return rules, err
|
||||
} else {
|
||||
rules = secgrp.Permissions
|
||||
}
|
||||
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) addSecurityGroupRules(secGrpId string, rule *secrules.SecurityRule) error {
|
||||
if len(rule.Ports) != 0 {
|
||||
for _, port := range rule.Ports {
|
||||
rule.PortStart, rule.PortEnd = port, port
|
||||
if err := self.addSecurityGroupRule(secGrpId, rule); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return self.addSecurityGroupRule(secGrpId, rule)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) addSecurityGroupRule(secGrpId string, rule *secrules.SecurityRule) error {
|
||||
ipPermissions, err := YunionSecRuleToAws(*rule)
|
||||
log.Debugf("Aws security group rule: %s", ipPermissions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if rule.Direction == secrules.SecurityRuleIngress {
|
||||
params := &ec2.AuthorizeSecurityGroupIngressInput{}
|
||||
params.SetGroupId(secGrpId)
|
||||
params.SetIpPermissions(ipPermissions)
|
||||
_, err := self.ec2Client.AuthorizeSecurityGroupIngress(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if rule.Direction == secrules.SecurityRuleEgress {
|
||||
params := &ec2.AuthorizeSecurityGroupEgressInput{}
|
||||
params.SetGroupId(secGrpId)
|
||||
params.SetIpPermissions(ipPermissions)
|
||||
_, err := self.ec2Client.AuthorizeSecurityGroupEgress(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) delSecurityGroupRule(secGrpId string, rule *secrules.SecurityRule) error {
|
||||
ipPermissions, err := YunionSecRuleToAws(*rule)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if rule.Direction == secrules.SecurityRuleIngress {
|
||||
params := &ec2.RevokeSecurityGroupIngressInput{}
|
||||
params.SetGroupId(secGrpId)
|
||||
params.SetIpPermissions(ipPermissions)
|
||||
_, err := self.ec2Client.RevokeSecurityGroupIngress(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if rule.Direction == secrules.SecurityRuleEgress {
|
||||
params := &ec2.RevokeSecurityGroupEgressInput{}
|
||||
params.SetGroupId(secGrpId)
|
||||
params.SetIpPermissions(ipPermissions)
|
||||
_, err := self.ec2Client.RevokeSecurityGroupEgress(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) updateSecurityGroupRuleDescription(secGrpId string, rule *secrules.SecurityRule) error {
|
||||
ipPermissions, err := YunionSecRuleToAws(*rule)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if rule.Direction == secrules.SecurityRuleIngress {
|
||||
params := &ec2.UpdateSecurityGroupRuleDescriptionsIngressInput{}
|
||||
params.SetGroupId(secGrpId)
|
||||
params.SetIpPermissions(ipPermissions)
|
||||
ret, err := self.ec2Client.UpdateSecurityGroupRuleDescriptionsIngress(params)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if ret.Return != nil && *ret.Return == false {
|
||||
log.Debugf("update security group %s rule description failed: %s", secGrpId, ipPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
if rule.Direction == secrules.SecurityRuleEgress {
|
||||
params := &ec2.UpdateSecurityGroupRuleDescriptionsEgressInput{}
|
||||
params.SetGroupId(secGrpId)
|
||||
params.SetIpPermissions(ipPermissions)
|
||||
ret, err := self.ec2Client.UpdateSecurityGroupRuleDescriptionsEgress(params)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if ret.Return != nil && *ret.Return == false {
|
||||
log.Debugf("update security group %s rule description failed: %s", secGrpId, ipPermissions)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) createSecurityGroup(vpcId string, name string, secgroupIdTag string, desc string) (string, error) {
|
||||
params := &ec2.CreateSecurityGroupInput{}
|
||||
params.SetVpcId(vpcId)
|
||||
params.SetDescription(desc)
|
||||
params.SetGroupName(name)
|
||||
|
||||
group, err := self.ec2Client.CreateSecurityGroup(params)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
tagspec := TagSpec{ResourceType: "security-group"}
|
||||
tagspec.SetTag("id", secgroupIdTag)
|
||||
tags, _ := tagspec.GetTagSpecifications()
|
||||
tagParams := &ec2.CreateTagsInput{}
|
||||
tagParams.SetResources([]*string{group.GroupId})
|
||||
tagParams.SetTags(tags.Tags)
|
||||
_, err = self.ec2Client.CreateTags(tagParams)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return *group.GroupId, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) createDefaultSecurityGroup(vpcId string) (string, error) {
|
||||
secId, err := self.createSecurityGroup(vpcId, "vpc default", fmt.Sprintf("%s-default", vpcId), "vpc default group")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
rule := &secrules.SecurityRule{
|
||||
Priority: 1,
|
||||
Action: secrules.SecurityRuleAllow,
|
||||
Protocol: "",
|
||||
Direction: secrules.SecurityRuleIngress,
|
||||
PortStart: -1,
|
||||
PortEnd: -1,
|
||||
}
|
||||
|
||||
err = self.addSecurityGroupRule(secId, rule)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return secId, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetSecurityGroupDetails(secGroupId string) (*SSecurityGroup, error) {
|
||||
params := &ec2.DescribeSecurityGroupsInput{}
|
||||
params.SetGroupIds([]*string{&secGroupId})
|
||||
|
||||
ret, err := self.ec2Client.DescribeSecurityGroups(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(ret.SecurityGroups) == 1 {
|
||||
s := ret.SecurityGroups[0]
|
||||
vpc, err := self.getVpc(*s.VpcId)
|
||||
if err != nil {
|
||||
fmt.Errorf("vpc %s not found", *s.VpcId)
|
||||
}
|
||||
|
||||
permissions := self.getSecRules(s.IpPermissions, s.IpPermissionsEgress)
|
||||
|
||||
return &SSecurityGroup{
|
||||
vpc: vpc,
|
||||
Description: *s.Description,
|
||||
SecurityGroupId: *s.GroupId,
|
||||
SecurityGroupName: *s.GroupName,
|
||||
VpcId: *s.VpcId,
|
||||
Permissions: permissions,
|
||||
RegionId: self.RegionId,
|
||||
}, nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("required one security group. but found: %d", len(ret.SecurityGroups))
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) getSecurityGroupByTag(vpcId, secgroupId string) (*SSecurityGroup, error) {
|
||||
secgroups, total, err := self.GetSecurityGroups(vpcId, secgroupId, 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if total != 1 {
|
||||
log.Debugf("failed to find SecurityGroup %s: %d found", secgroupId, total)
|
||||
return nil, httperrors.NewNotFoundError("failed to find SecurityGroup %s", secgroupId)
|
||||
}
|
||||
return &secgroups[0], nil
|
||||
}
|
||||
|
||||
func (self *SRegion) addTagToSecurityGroup(secgroupId, key, value string, index int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) modifySecurityGroup(secGrpId string, name string, desc string) error {
|
||||
tagspec := TagSpec{ResourceType: "security-group"}
|
||||
tagspec.SetNameTag(name)
|
||||
tagspec.SetDescTag(desc)
|
||||
ec2Tags, _ := tagspec.GetTagSpecifications()
|
||||
params := &ec2.CreateTagsInput{}
|
||||
params.SetTags(ec2Tags.Tags)
|
||||
params.SetResources([]*string{&secGrpId})
|
||||
|
||||
_, err := self.ec2Client.CreateTags(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) syncSecgroupRules(secgroupId string, rules []secrules.SecurityRule) error {
|
||||
if secgroup, err := self.GetSecurityGroupDetails(secgroupId); err != nil {
|
||||
return err
|
||||
} else {
|
||||
|
||||
sort.Sort(secrules.SecurityRuleSet(rules))
|
||||
sort.Sort(secrules.SecurityRuleSet(secgroup.Permissions))
|
||||
|
||||
i, j := 0, 0
|
||||
for i < len(rules) || j < len(secgroup.Permissions) {
|
||||
if i < len(rules) && j < len(secgroup.Permissions) {
|
||||
permissionStr := secgroup.Permissions[j].String()
|
||||
ruleStr := rules[i].String()
|
||||
cmp := strings.Compare(permissionStr, ruleStr)
|
||||
if cmp == 0 {
|
||||
if secgroup.Permissions[j].Description != rules[i].Description {
|
||||
if err := self.updateSecurityGroupRuleDescription(secgroupId, &rules[i]); err != nil {
|
||||
log.Errorf("updateSecurityGroupRuleDescription error %v", rules[i])
|
||||
return err
|
||||
}
|
||||
}
|
||||
i += 1
|
||||
j += 1
|
||||
} else if cmp > 0 {
|
||||
if err := self.delSecurityGroupRule(secgroupId, &secgroup.Permissions[j]); err != nil {
|
||||
log.Errorf("delSecurityGroupRule error %v", secgroup.Permissions[j])
|
||||
return err
|
||||
}
|
||||
j += 1
|
||||
} else {
|
||||
if err := self.addSecurityGroupRules(secgroupId, &rules[i]); err != nil {
|
||||
log.Errorf("addSecurityGroupRule error %v", rules[i])
|
||||
return err
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
} else if i >= len(rules) {
|
||||
if err := self.delSecurityGroupRule(secgroupId, &secgroup.Permissions[j]); err != nil {
|
||||
log.Errorf("delSecurityGroupRule error %v", secgroup.Permissions[j])
|
||||
return err
|
||||
}
|
||||
j += 1
|
||||
} else if j >= len(secgroup.Permissions) {
|
||||
if err := self.addSecurityGroupRules(secgroupId, &rules[i]); err != nil {
|
||||
log.Errorf("addSecurityGroupRule error %v", rules[i])
|
||||
return err
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) getSecRules(ingress []*ec2.IpPermission, egress []*ec2.IpPermission) []secrules.SecurityRule {
|
||||
rules := []secrules.SecurityRule{}
|
||||
for _, p := range ingress {
|
||||
ret, err := AwsIpPermissionToYunion(secrules.SecurityRuleIngress, *p)
|
||||
if err != nil {
|
||||
log.Debugf(err.Error())
|
||||
}
|
||||
|
||||
for _, rule := range ret {
|
||||
rules = append(rules, rule)
|
||||
}
|
||||
}
|
||||
|
||||
for _, p := range egress {
|
||||
ret, err := AwsIpPermissionToYunion(secrules.SecurityRuleEgress, *p)
|
||||
if err != nil {
|
||||
log.Debugf(err.Error())
|
||||
}
|
||||
|
||||
for _, rule := range ret {
|
||||
rules = append(rules, rule)
|
||||
}
|
||||
}
|
||||
|
||||
return rules
|
||||
}
|
||||
|
||||
func (self *SRegion) GetSecurityGroups(vpcId string, secgroupIdTag string, offset int, limit int) ([]SSecurityGroup, int, error) {
|
||||
params := &ec2.DescribeSecurityGroupsInput{}
|
||||
filters := make([]*ec2.Filter, 0)
|
||||
if len(vpcId) > 0 {
|
||||
filters = AppendSingleValueFilter(filters, "vpc-id", vpcId)
|
||||
}
|
||||
|
||||
if len(secgroupIdTag) > 0 {
|
||||
filters = AppendSingleValueFilter(filters, "tag:id", secgroupIdTag)
|
||||
}
|
||||
|
||||
if len(filters) > 0 {
|
||||
params.SetFilters(filters)
|
||||
}
|
||||
|
||||
ret, err := self.ec2Client.DescribeSecurityGroups(params)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
securityGroups := []SSecurityGroup{}
|
||||
for _, item := range ret.SecurityGroups {
|
||||
if err := FillZero(item); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if len(*item.VpcId) == 0 {
|
||||
log.Debugf("ingored: security group with no vpc binded")
|
||||
continue
|
||||
}
|
||||
|
||||
vpc, err := self.getVpc(*item.VpcId)
|
||||
if err != nil {
|
||||
log.Errorf("vpc %s not found", *item.VpcId)
|
||||
continue
|
||||
}
|
||||
|
||||
permissions := self.getSecRules(item.IpPermissions, item.IpPermissionsEgress)
|
||||
group := SSecurityGroup{
|
||||
vpc: vpc,
|
||||
Description: *item.Description,
|
||||
SecurityGroupId: *item.GroupId,
|
||||
SecurityGroupName: *item.GroupName,
|
||||
VpcId: *item.VpcId,
|
||||
Permissions: permissions,
|
||||
RegionId: self.RegionId,
|
||||
// Tags: *item.Tags,
|
||||
}
|
||||
|
||||
securityGroups = append(securityGroups, group)
|
||||
}
|
||||
|
||||
return securityGroups, len(securityGroups), nil
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/aws"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type DiskListOptions struct {
|
||||
Instance string `help:"Instance ID"`
|
||||
Zone string `help:"Zone ID"`
|
||||
Category string `help:"Disk category"`
|
||||
Offset int `help:"List offset"`
|
||||
Limit int `help:"List limit"`
|
||||
}
|
||||
shellutils.R(&DiskListOptions{}, "disk-list", "List disks", func(cli *aws.SRegion, args *DiskListOptions) error {
|
||||
disks, total, e := cli.GetDisks(args.Instance, args.Zone, args.Category, nil, args.Offset, args.Limit)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printList(disks, total, args.Offset, args.Limit, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type DiskDeleteOptions struct {
|
||||
Instance string `help:"Instance ID"`
|
||||
}
|
||||
shellutils.R(&DiskDeleteOptions{}, "disk-delete", "List disks", func(cli *aws.SRegion, args *DiskDeleteOptions) error {
|
||||
e := cli.DeleteDisk(args.Instance)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package shell // import "yunion.io/x/onecloud/pkg/util/aws/shell"
|
||||
@@ -0,0 +1,53 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/aws"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type EipListOptions struct {
|
||||
Offset int `help:"List offset"`
|
||||
Limit int `help:"List limit"`
|
||||
}
|
||||
shellutils.R(&EipListOptions{}, "eip-list", "List eips", func(cli *aws.SRegion, args *EipListOptions) error {
|
||||
eips, total, e := cli.GetEips("", args.Offset, args.Limit)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printList(eips, total, args.Offset, args.Limit, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type EipAllocateOptions struct {
|
||||
}
|
||||
shellutils.R(&EipAllocateOptions{}, "eip-create", "Allocate an EIP", func(cli *aws.SRegion, args *EipAllocateOptions) error {
|
||||
eip, err := cli.AllocateEIP("vpc")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(eip)
|
||||
return nil
|
||||
})
|
||||
|
||||
type EipReleaseOptions struct {
|
||||
ID string `help:"EIP allocation ID"`
|
||||
}
|
||||
shellutils.R(&EipReleaseOptions{}, "eip-delete", "Release an EIP", func(cli *aws.SRegion, args *EipReleaseOptions) error {
|
||||
err := cli.DeallocateEIP(args.ID)
|
||||
return err
|
||||
})
|
||||
|
||||
type EipAssociateOptions struct {
|
||||
ID string `help:"EIP allocation ID"`
|
||||
INSTANCE string `help:"Instance ID"`
|
||||
}
|
||||
shellutils.R(&EipAssociateOptions{}, "eip-associate", "Associate an EIP", func(cli *aws.SRegion, args *EipAssociateOptions) error {
|
||||
err := cli.AssociateEip(args.ID, args.INSTANCE)
|
||||
return err
|
||||
})
|
||||
shellutils.R(&EipAssociateOptions{}, "eip-dissociate", "Dissociate an EIP", func(cli *aws.SRegion, args *EipAssociateOptions) error {
|
||||
err := cli.DissociateEip(args.ID, args.INSTANCE)
|
||||
return err
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/aws"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type ImageListOptions struct {
|
||||
Status string `help:"image status type" choices:"Creating|Available|UnAvailable|CreateFailed"`
|
||||
Owner string `help:"Owner type" choices:"amazon|self|microsoft|aws-marketplace"`
|
||||
Id []string `help:"Image ID"`
|
||||
Name string `help:"image name"`
|
||||
Limit int `help:"page size"`
|
||||
Offset int `help:"page offset"`
|
||||
}
|
||||
shellutils.R(&ImageListOptions{}, "image-list", "List images", func(cli *aws.SRegion, args *ImageListOptions) error {
|
||||
images, total, e := cli.GetImages(aws.ImageStatusType(args.Status), aws.ImageOwnerType(args.Owner), args.Id, args.Name, args.Offset, args.Limit)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printList(images, total, args.Offset, args.Limit, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type ImageDeleteOptions struct {
|
||||
ID string `help:"ID or Name to delete"`
|
||||
}
|
||||
shellutils.R(&ImageDeleteOptions{}, "image-delete", "Delete image", func(cli *aws.SRegion, args *ImageDeleteOptions) error {
|
||||
return cli.DeleteImage(args.ID)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/util/aws"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type InstanceListOptions struct {
|
||||
Id []string `help:"IDs of instances to show"`
|
||||
Zone string `help:"Zone ID"`
|
||||
Limit int `help:"page size"`
|
||||
Offset int `help:"page offset"`
|
||||
}
|
||||
shellutils.R(&InstanceListOptions{}, "instance-list", "List intances", func(cli *aws.SRegion, args *InstanceListOptions) error {
|
||||
instances, total, e := cli.GetInstances(args.Zone, args.Id, args.Offset, args.Limit)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printList(instances, total, args.Offset, args.Limit, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type InstanceCrateOptions struct {
|
||||
NAME string `help:"name of instance"`
|
||||
IMAGE string `help:"image ID"`
|
||||
CPU int `help:"CPU count"`
|
||||
MEMORYGB int `help:"MemoryGB"`
|
||||
Disk []int `help:"Data disk sizes int GB"`
|
||||
STORAGE string `help:"Storage type" choices:"gp2|io1|st1|sc1|standard"`
|
||||
NETWORK string `help:"Network ID"`
|
||||
PUBLICKEY string `help:"PublicKey file path"`
|
||||
}
|
||||
shellutils.R(&InstanceCrateOptions{}, "instance-create", "Create a instance", func(cli *aws.SRegion, args *InstanceCrateOptions) error {
|
||||
content, err := ioutil.ReadFile(args.PUBLICKEY)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
instance, e := cli.CreateInstanceSimple(args.NAME, args.IMAGE, args.CPU, args.MEMORYGB, args.STORAGE, args.Disk, args.NETWORK, string(content))
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printObject(instance)
|
||||
return nil
|
||||
})
|
||||
|
||||
type InstanceDiskOperationOptions struct {
|
||||
ID string `help:"instance ID"`
|
||||
DISK string `help:"disk ID"`
|
||||
}
|
||||
|
||||
type InstanceDiskAttachOptions struct {
|
||||
ID string `help:"instance ID"`
|
||||
DISK string `help:"disk ID"`
|
||||
DEVICE string `help:"disk device name. eg. /dev/sdb"`
|
||||
}
|
||||
|
||||
shellutils.R(&InstanceDiskAttachOptions{}, "instance-attach-disk", "Attach a disk to instance", func(cli *aws.SRegion, args *InstanceDiskAttachOptions) error {
|
||||
err := cli.AttachDisk(args.ID, args.DISK, args.DEVICE)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
shellutils.R(&InstanceDiskOperationOptions{}, "instance-detach-disk", "Detach a disk to instance", func(cli *aws.SRegion, args *InstanceDiskOperationOptions) error {
|
||||
err := cli.DetachDisk(args.ID, args.DISK)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
type InstanceOperationOptions struct {
|
||||
ID string `help:"instance ID"`
|
||||
}
|
||||
shellutils.R(&InstanceOperationOptions{}, "instance-start", "Start a instance", func(cli *aws.SRegion, args *InstanceOperationOptions) error {
|
||||
err := cli.StartVM(args.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
type InstanceStopOptions struct {
|
||||
ID string `help:"instance ID"`
|
||||
Force bool `help:"Force stop instance"`
|
||||
}
|
||||
shellutils.R(&InstanceStopOptions{}, "instance-stop", "Stop a instance", func(cli *aws.SRegion, args *InstanceStopOptions) error {
|
||||
err := cli.StopVM(args.ID, args.Force)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
shellutils.R(&InstanceOperationOptions{}, "instance-delete", "Delete a instance", func(cli *aws.SRegion, args *InstanceOperationOptions) error {
|
||||
err := cli.DeleteVM(args.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
/*
|
||||
server-change-config 更改系统配置
|
||||
server-reset
|
||||
*/
|
||||
type InstanceDeployOptions struct {
|
||||
ID string `help:"instance ID"`
|
||||
Name string `help:"new instance name"`
|
||||
Hostname string `help:"new hostname"`
|
||||
Keypair string `help:"Keypair Name"`
|
||||
DeleteKeypair bool `help:"Remove SSH keypair"`
|
||||
Password string `help:"new password"`
|
||||
// ResetPassword bool `help:"Force reset password"`
|
||||
Description string `help:"new instances description"`
|
||||
}
|
||||
|
||||
shellutils.R(&InstanceDeployOptions{}, "instance-deploy", "Deploy keypair/password to a stopped virtual server", func(cli *aws.SRegion, args *InstanceDeployOptions) error {
|
||||
err := cli.DeployVM(args.ID, args.Name, args.Password, args.Keypair, args.DeleteKeypair, args.Description)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
type InstanceRebuildRootOptions struct {
|
||||
ID string `help:"instance ID"`
|
||||
Image string `help:"Image ID"`
|
||||
Size int `help:"system disk size in GB"`
|
||||
}
|
||||
|
||||
shellutils.R(&InstanceRebuildRootOptions{}, "instance-rebuild-root", "Reinstall virtual server system image", func(cli *aws.SRegion, args *InstanceRebuildRootOptions) error {
|
||||
diskID, err := cli.ReplaceSystemDisk(args.ID, args.Image, args.Size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("New diskID is %s", diskID)
|
||||
return nil
|
||||
})
|
||||
|
||||
type InstanceChangeConfigOptions struct {
|
||||
ID string `help:"instance ID"`
|
||||
Ncpu int `help:"number of CPU"`
|
||||
Vmem int `help:"MiB of memory"`
|
||||
Disk []int `help:"Data disk sizes int GB"`
|
||||
}
|
||||
|
||||
shellutils.R(&InstanceChangeConfigOptions{}, "instance-change-config", "Deploy keypair/password to a stopped virtual server", func(cli *aws.SRegion, args *InstanceChangeConfigOptions) error {
|
||||
instance, e := cli.GetInstance(args.ID)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
|
||||
// todo : add create disks
|
||||
err := cli.ChangeVMConfig(instance.ZoneId, args.ID, args.Ncpu, args.Vmem, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/aws"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type InstanceTypeListOptions struct {
|
||||
}
|
||||
shellutils.R(&InstanceTypeListOptions{}, "instance-type-list", "List intance types", func(cli *aws.SRegion, args *InstanceTypeListOptions) error {
|
||||
instanceTypes, e := cli.GetInstanceTypes()
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printList(instanceTypes, 0, 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type InstanceMatchOptions struct {
|
||||
CPU int `help:"CPU count"`
|
||||
MEM int `help:"Memory in MB"`
|
||||
GPU int `help:"GPU size"`
|
||||
Zone string `help:"Test in zone"`
|
||||
}
|
||||
shellutils.R(&InstanceMatchOptions{}, "instance-type-select", "Select matching instance types", func(cli *aws.SRegion, args *InstanceMatchOptions) error {
|
||||
instanceTypes, e := cli.GetMatchInstanceTypes(args.CPU, args.MEM, args.GPU, args.Zone)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printList(instanceTypes, 0, 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/aws"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type KeyPairListOptions struct {
|
||||
Limit int `help:"page size"`
|
||||
Offset int `help:"page offset"`
|
||||
}
|
||||
shellutils.R(&KeyPairListOptions{}, "keypair-list", "List keypairs", func(cli *aws.SRegion, args *KeyPairListOptions) error {
|
||||
keypairs, total, e := cli.GetKeypairs("", "", args.Offset, args.Limit)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printList(keypairs, total, args.Offset, args.Limit, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type KeyPairImportOptions struct {
|
||||
NAME string `help:"Name of new keypair"`
|
||||
PUBKEY string `help:"Public key string"`
|
||||
}
|
||||
shellutils.R(&KeyPairImportOptions{}, "keypair-import", "Import a keypair", func(cli *aws.SRegion, args *KeyPairImportOptions) error {
|
||||
keypair, err := cli.ImportKeypair(args.NAME, args.PUBKEY)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(keypair)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/aws"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type VSwitchListOptions struct {
|
||||
Limit int `help:"page size"`
|
||||
Offset int `help:"page offset"`
|
||||
}
|
||||
shellutils.R(&VSwitchListOptions{}, "vswitch-list", "List vswitches", func(cli *aws.SRegion, args *VSwitchListOptions) error {
|
||||
vswitches, total, e := cli.GetNetwroks(nil, "", args.Offset, args.Limit)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printList(vswitches, total, args.Offset, args.Limit, []string{})
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package shell
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/util/printutils"
|
||||
|
||||
func printList(data interface{}, total, offset, limit int, columns []string) {
|
||||
printutils.PrintInterfaceList(data, total, offset, limit, columns)
|
||||
}
|
||||
|
||||
func printObject(obj interface{}) {
|
||||
printutils.PrintInterfaceObject(obj)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/aws"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type RegionListOptions struct {
|
||||
}
|
||||
shellutils.R(&RegionListOptions{}, "region-list", "List regions", func(cli *aws.SRegion, args *RegionListOptions) error {
|
||||
regions := cli.GetClient().GetRegions()
|
||||
printList(regions, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/aws"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type SecurityGroupListOptions struct {
|
||||
VpcId string `help:"VPC ID"`
|
||||
Limit int `help:"page size"`
|
||||
Offset int `help:"page offset"`
|
||||
}
|
||||
shellutils.R(&SecurityGroupListOptions{}, "security-group-list", "List security group", func(cli *aws.SRegion, args *SecurityGroupListOptions) error {
|
||||
secgrps, total, e := cli.GetSecurityGroups(args.VpcId, "", args.Offset, args.Limit)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printList(secgrps, total, args.Offset, args.Limit, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type SecurityGroupShowOptions struct {
|
||||
ID string `help:"ID or name of security group"`
|
||||
}
|
||||
shellutils.R(&SecurityGroupShowOptions{}, "security-group-show", "Show details of a security group", func(cli *aws.SRegion, args *SecurityGroupShowOptions) error {
|
||||
secgrp, err := cli.GetSecurityGroupDetails(args.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(secgrp)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/aws"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type SnapshotListOptions struct {
|
||||
DiskId string `help:"Disk ID"`
|
||||
InstanceId string `help:"Instance ID"`
|
||||
SnapshotIds []string `helo:"Snapshot ids"`
|
||||
Name string `help:"Snapshot Name"`
|
||||
Limit int `help:"page size"`
|
||||
Offset int `help:"page offset"`
|
||||
}
|
||||
shellutils.R(&SnapshotListOptions{}, "snapshot-list", "List snapshot", func(cli *aws.SRegion, args *SnapshotListOptions) error {
|
||||
if snapshots, total, err := cli.GetSnapshots(args.InstanceId, args.DiskId, args.Name, args.SnapshotIds, args.Offset, args.Limit); err != nil {
|
||||
return err
|
||||
} else {
|
||||
printList(snapshots, total, args.Offset, args.Limit, []string{})
|
||||
return nil
|
||||
}
|
||||
})
|
||||
|
||||
type SnapshotDeleteOptions struct {
|
||||
ID string `help:"Snapshot ID"`
|
||||
}
|
||||
|
||||
shellutils.R(&SnapshotDeleteOptions{}, "snapshot-delete", "Delete snapshot", func(cli *aws.SRegion, args *SnapshotDeleteOptions) error {
|
||||
return cli.DeleteSnapshot(args.ID)
|
||||
})
|
||||
|
||||
type SnapshotCreateOptions struct {
|
||||
DiskId string `help:"Disk ID"`
|
||||
Name string `help:"Snapeshot Name"`
|
||||
Desc string `help:"Snapshot Desc"`
|
||||
}
|
||||
|
||||
shellutils.R(&SnapshotCreateOptions{}, "snapshot-create", "Create snapshot", func(cli *aws.SRegion, args *SnapshotCreateOptions) error {
|
||||
_, err := cli.CreateSnapshot(args.DiskId, args.Name, args.Desc)
|
||||
return err
|
||||
})
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/aws"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type VpcListOptions struct {
|
||||
Limit int `help:"page size"`
|
||||
Offset int `help:"page offset"`
|
||||
}
|
||||
shellutils.R(&VpcListOptions{}, "vpc-list", "List vpcs", func(cli *aws.SRegion, args *VpcListOptions) error {
|
||||
vpcs, total, e := cli.GetVpcs(nil, args.Offset, args.Limit)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printList(vpcs, total, args.Offset, args.Limit, []string{})
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/aws"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type ZoneListOptions struct {
|
||||
Details bool `help:"show Details"`
|
||||
// ChargeType string `help:"charge type" choices:"PrePaid|PostPaid" default:"PrePaid"`
|
||||
// SpotStrategy string `help:"Spot strategy, NoSpot|SpotWithPriceLimit|SpotAsPriceGo" choices:"NoSpot|SpotWithPriceLimit|SpotAsPriceGo" default:"NoSpot"`
|
||||
}
|
||||
shellutils.R(&ZoneListOptions{}, "zone-list", "List zones", func(cli *aws.SRegion, args *ZoneListOptions) error {
|
||||
zones, e := cli.GetIZones()
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
cols := []string{"zone_id", "local_name", "available_resource_creation", "available_disk_categories"}
|
||||
if args.Details {
|
||||
cols = []string{}
|
||||
}
|
||||
printList(zones, 0, 0, 0, cols)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
type SnapshotStatusType string
|
||||
|
||||
const (
|
||||
SnapshotStatusAccomplished SnapshotStatusType = "accomplished"
|
||||
SnapshotStatusProgress SnapshotStatusType = "progressing"
|
||||
SnapshotStatusFailed SnapshotStatusType = "failed"
|
||||
)
|
||||
|
||||
type SSnapshot struct {
|
||||
region *SRegion
|
||||
|
||||
Progress string
|
||||
SnapshotId string
|
||||
SnapshotName string
|
||||
SourceDiskId string
|
||||
SourceDiskSize int32
|
||||
SourceDiskType string
|
||||
Status SnapshotStatusType
|
||||
Usage string
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetDiskType() string {
|
||||
// todo: self.SourceDiskType
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetId() string {
|
||||
return self.SnapshotId
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetName() string {
|
||||
return self.SnapshotName
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetGlobalId() string {
|
||||
return fmt.Sprintf("%s", self.SnapshotId)
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetStatus() string {
|
||||
// todo: implement me
|
||||
if self.Status == SnapshotStatusAccomplished {
|
||||
return models.SNAPSHOT_READY
|
||||
} else if self.Status == SnapshotStatusProgress {
|
||||
return models.SNAPSHOT_CREATING
|
||||
} else { // if self.Status == SnapshotStatusFailed
|
||||
return models.SNAPSHOT_FAILED
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SSnapshot) Refresh() error {
|
||||
if snapshots, total, err := self.region.GetSnapshots("", "", "", []string{self.SnapshotId}, 0, 1); err != nil {
|
||||
return err
|
||||
} else if total != 1 {
|
||||
return cloudprovider.ErrNotFound
|
||||
} else if err := jsonutils.Update(self, snapshots[0]); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SSnapshot) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetMetadata() *jsonutils.JSONDict {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetManagerId() string {
|
||||
return self.region.client.providerId
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetSize() int32 {
|
||||
return self.SourceDiskSize
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetDiskId() string {
|
||||
return self.SourceDiskId
|
||||
}
|
||||
|
||||
func (self *SSnapshot) Delete() error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetRegionId() string {
|
||||
return self.region.GetId()
|
||||
}
|
||||
|
||||
func (self *SRegion) GetSnapshots(instanceId string, diskId string, snapshotName string, snapshotIds []string, offset int, limit int) ([]SSnapshot, int, error) {
|
||||
params := &ec2.DescribeSnapshotsInput{}
|
||||
filters := make([]*ec2.Filter, 0)
|
||||
// todo: not support search by instancesId. use Tag?
|
||||
// if len(instanceId) > o {
|
||||
// filters = AppendSingleValueFilter(filters, )
|
||||
// }
|
||||
// owner by self
|
||||
owner := "self"
|
||||
params.SetOwnerIds([]*string{&owner})
|
||||
if len(diskId) > 0 {
|
||||
filters = AppendSingleValueFilter(filters, "volume-id", diskId)
|
||||
}
|
||||
|
||||
// not supported. use Tag?
|
||||
// if len(snapshotName) > 0 {
|
||||
// filters = AppendSingleValueFilter(filters, "volume-id", diskId)
|
||||
// }
|
||||
if len(filters) > 0 {
|
||||
params.SetFilters(filters)
|
||||
}
|
||||
|
||||
if len(snapshotIds) > 0 {
|
||||
params.SetSnapshotIds(ConvertedList(snapshotIds))
|
||||
}
|
||||
|
||||
ret, err := self.ec2Client.DescribeSnapshots(params)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
snapshots := []SSnapshot{}
|
||||
for _, item := range ret.Snapshots {
|
||||
if err := FillZero(item); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
snapshot := SSnapshot{}
|
||||
snapshot.SnapshotId = *item.SnapshotId
|
||||
snapshot.Status = SnapshotStatusType(*item.State)
|
||||
snapshot.region = self
|
||||
snapshot.Progress = *item.Progress
|
||||
snapshot.SnapshotName = *item.SnapshotId
|
||||
snapshot.SourceDiskId = *item.VolumeId
|
||||
snapshot.SourceDiskSize = int32(*item.VolumeSize)
|
||||
// snapshot.SourceDiskType
|
||||
snapshots = append(snapshots, snapshot)
|
||||
}
|
||||
|
||||
return snapshots, len(snapshots), nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetISnapshotById(snapshotId string) (cloudprovider.ICloudSnapshot, error) {
|
||||
if snapshots, total, err := self.GetSnapshots("", "", "", []string{snapshotId}, 0, 1); err != nil {
|
||||
return nil, err
|
||||
} else if total != 1 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
} else {
|
||||
return &snapshots[0], nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateSnapshot(diskId, name, desc string) (string, error) {
|
||||
params := &ec2.CreateSnapshotInput{}
|
||||
if len(diskId) <= 0 {
|
||||
return "", fmt.Errorf("disk id should not be empty")
|
||||
} else {
|
||||
params.SetVolumeId(diskId)
|
||||
}
|
||||
|
||||
if len(name) <= 0 {
|
||||
return "", fmt.Errorf("name length should great than 0")
|
||||
} else {
|
||||
tagspec := TagSpec{ResourceType: "snapshot"}
|
||||
tagspec.SetNameTag(name)
|
||||
ec2Tag, _ := tagspec.GetTagSpecifications()
|
||||
params.SetTagSpecifications([]*ec2.TagSpecification{ec2Tag})
|
||||
}
|
||||
|
||||
params.SetDescription(desc)
|
||||
_, err := self.ec2Client.CreateSnapshot(params)
|
||||
return "", err
|
||||
}
|
||||
|
||||
func (self *SRegion) DeleteSnapshot(snapshotId string) error {
|
||||
params := &ec2.DeleteSnapshotInput{}
|
||||
params.SetSnapshotId(snapshotId)
|
||||
_, err := self.ec2Client.DeleteSnapshot(params)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
type SStorage struct {
|
||||
zone *SZone
|
||||
storageType string
|
||||
}
|
||||
|
||||
func (self *SStorage) GetId() string {
|
||||
return fmt.Sprintf("%s-%s-%s", self.zone.region.client.providerId, self.zone.GetId(), self.storageType)
|
||||
}
|
||||
|
||||
func (self *SStorage) GetName() string {
|
||||
return fmt.Sprintf("%s-%s-%s", self.zone.region.client.providerName, self.zone.GetId(), self.storageType)
|
||||
}
|
||||
|
||||
func (self *SStorage) GetGlobalId() string {
|
||||
return fmt.Sprintf("%s-%s-%s", self.zone.region.client.providerId, self.zone.GetGlobalId(), self.storageType)
|
||||
}
|
||||
|
||||
func (self *SStorage) GetStatus() string {
|
||||
return models.STORAGE_ONLINE
|
||||
}
|
||||
|
||||
func (self *SStorage) Refresh() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SStorage) IsEmulated() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SStorage) GetMetadata() *jsonutils.JSONDict {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SStorage) GetIStoragecache() cloudprovider.ICloudStoragecache {
|
||||
return self.zone.region.getStoragecache()
|
||||
}
|
||||
|
||||
func (self *SStorage) GetIZone() cloudprovider.ICloudZone {
|
||||
return self.zone
|
||||
}
|
||||
|
||||
func (self *SStorage) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
|
||||
disks := make([]SDisk, 0)
|
||||
for {
|
||||
parts, total, err := self.zone.region.GetDisks("", self.zone.GetId(), self.storageType, nil, len(disks), 50)
|
||||
if err != nil {
|
||||
log.Errorf("GetDisks fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
disks = append(disks, parts...)
|
||||
if len(disks) >= total {
|
||||
break
|
||||
}
|
||||
}
|
||||
idisks := make([]cloudprovider.ICloudDisk, len(disks))
|
||||
for i := 0; i < len(disks); i += 1 {
|
||||
disks[i].storage = self
|
||||
idisks[i] = &disks[i]
|
||||
}
|
||||
return idisks, nil
|
||||
}
|
||||
|
||||
func (self *SStorage) GetStorageType() string {
|
||||
return self.storageType
|
||||
}
|
||||
|
||||
func (self *SStorage) GetMediumType() string {
|
||||
if self.storageType == models.STORAGE_GP2_SSD || self.storageType == models.STORAGE_IO1_SSD {
|
||||
return models.DISK_TYPE_SSD
|
||||
} else {
|
||||
return models.DISK_TYPE_ROTATE
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SStorage) GetCapacityMB() int {
|
||||
return 0 // unlimited
|
||||
}
|
||||
|
||||
func (self *SStorage) GetStorageConf() jsonutils.JSONObject {
|
||||
conf := jsonutils.NewDict()
|
||||
return conf
|
||||
}
|
||||
|
||||
func (self *SStorage) GetEnabled() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SStorage) GetManagerId() string {
|
||||
return self.zone.region.client.providerId
|
||||
}
|
||||
|
||||
func (self *SStorage) CreateIDisk(name string, sizeGb int, desc string) (cloudprovider.ICloudDisk, error) {
|
||||
diskId, err := self.zone.region.CreateDisk(self.zone.ZoneId, self.storageType, name, sizeGb, "", desc)
|
||||
if err != nil {
|
||||
log.Errorf("createDisk fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
disk, err := self.zone.region.GetDisk(diskId)
|
||||
if err != nil {
|
||||
log.Errorf("getDisk fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
disk.storage = self
|
||||
return disk, nil
|
||||
}
|
||||
|
||||
func (self *SStorage) GetIDisk(idStr string) (cloudprovider.ICloudDisk, error) {
|
||||
if disk, err := self.zone.region.GetDisk(idStr); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
disk.storage = self
|
||||
return disk, nil
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,474 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/aws/aws-sdk-go/service/iam"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"time"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
)
|
||||
|
||||
type SStoragecache struct {
|
||||
region *SRegion
|
||||
|
||||
iimages []cloudprovider.ICloudImage
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetId() string {
|
||||
return fmt.Sprintf("%s-%s", self.region.client.providerId, self.region.GetId())
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetName() string {
|
||||
return fmt.Sprintf("%s-%s", self.region.client.providerName, self.region.GetId())
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetGlobalId() string {
|
||||
return fmt.Sprintf("%s-%s", self.region.client.providerId, self.region.GetGlobalId())
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetStatus() string {
|
||||
return "available"
|
||||
}
|
||||
|
||||
func (self *SStoragecache) Refresh() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SStoragecache) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetMetadata() *jsonutils.JSONDict {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetIImages() ([]cloudprovider.ICloudImage, error) {
|
||||
if self.iimages == nil {
|
||||
err := self.fetchImages()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return self.iimages, nil
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetManagerId() string {
|
||||
return self.region.client.providerId
|
||||
}
|
||||
|
||||
func (self *SStoragecache) CreateIImage(snapshotId, imageName, osType, imageDesc string) (cloudprovider.ICloudImage, error) {
|
||||
if imageId, err := self.region.createIImage(snapshotId, imageName, imageDesc); err != nil {
|
||||
return nil, err
|
||||
} else if image, err := self.region.GetImage(imageId); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
image.storageCache = self
|
||||
iimage := make([]cloudprovider.ICloudImage, 1)
|
||||
iimage[0] = image
|
||||
//todo : implement me
|
||||
if err := cloudprovider.WaitStatus(iimage[0], "avaliable", 15*time.Second, 3600*time.Second); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return iimage[0], nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SStoragecache) DownloadImage(userCred mcclient.TokenCredential, imageId string, extId string, path string) (jsonutils.JSONObject, error) {
|
||||
return self.downloadImage(userCred, imageId, extId)
|
||||
}
|
||||
|
||||
func (self *SStoragecache) UploadImage(userCred mcclient.TokenCredential, imageId string, osArch, osType, osDist string, extId string, isForce bool) (string, error) {
|
||||
if len(extId) > 0 {
|
||||
log.Debugf("UploadImage: Image external ID exists %s", extId)
|
||||
|
||||
status, err := self.region.GetImageStatus(extId)
|
||||
if err != nil {
|
||||
log.Errorf("GetImageStatus error %s", err)
|
||||
}
|
||||
if status == ImageStatusAvailable && !isForce {
|
||||
return extId, nil
|
||||
}
|
||||
} else {
|
||||
log.Debugf("UploadImage: no external ID")
|
||||
}
|
||||
|
||||
return self.uploadImage(userCred, imageId, osArch, osType, osDist, isForce)
|
||||
|
||||
}
|
||||
|
||||
func (self *SStoragecache) fetchImages() error {
|
||||
images := make([]SImage, 0)
|
||||
for {
|
||||
parts, total, err := self.region.GetImages(ImageStatusType(""), ImageOwnerSelf, nil, "", len(images), 50)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
images = append(images, parts...)
|
||||
if len(images) >= total {
|
||||
break
|
||||
}
|
||||
}
|
||||
self.iimages = make([]cloudprovider.ICloudImage, len(images))
|
||||
for i := 0; i < len(images); i += 1 {
|
||||
images[i].storageCache = self
|
||||
self.iimages[i] = &images[i]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SStoragecache) uploadImage(userCred mcclient.TokenCredential, imageId string, osArch, osType, osDist string, isForce bool) (string, error) {
|
||||
// todo: implement me
|
||||
bucketName := "imgcache-onecloud"
|
||||
err := self.region.initVmimport()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// first upload image to oss
|
||||
s := auth.GetAdminSession(options.Options.Region, "")
|
||||
|
||||
meta, reader, err := modules.Images.Download(s, imageId)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
log.Infof("meta data %s", meta)
|
||||
|
||||
diskFormat, err := meta.GetString("disk_format")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
s3Client, err := self.region.getS3Client()
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
// 内存?
|
||||
f, err := ioutil.ReadAll(reader)
|
||||
params := &s3.PutObjectInput{}
|
||||
params.SetBucket(bucketName)
|
||||
params.SetKey(imageId)
|
||||
params.SetBody(bytes.NewReader(f))
|
||||
_, err = s3Client.PutObject(params)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
imageBaseName := imageId
|
||||
if imageBaseName[0] >= '0' && imageBaseName[0] <= '9' {
|
||||
imageBaseName = fmt.Sprintf("img%s", imageId)
|
||||
}
|
||||
imageName := imageBaseName
|
||||
nameIdx := 1
|
||||
|
||||
// check image name, avoid name conflict
|
||||
for {
|
||||
_, err = self.region.GetImageByName(imageName)
|
||||
if err != nil {
|
||||
if err == cloudprovider.ErrNotFound {
|
||||
break
|
||||
} else {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
imageName = fmt.Sprintf("%s-%d", imageBaseName, nameIdx)
|
||||
nameIdx += 1
|
||||
}
|
||||
|
||||
task, err := self.region.ImportImage(imageName, osArch, osType, osDist, diskFormat, bucketName, imageId)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("ImportImage error %s %s %s", imageId, bucketName, err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
// todo:// 等待镜像导入完成
|
||||
for i := 1; i < 120; i++ {
|
||||
ret, err := self.region.ec2Client.DescribeImportImageTasks(&ec2.DescribeImportImageTasksInput{ImportTaskIds: []*string{&task.TaskId}})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
err = FillZero(ret)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
log.Debugf("DescribeImportImage Task %s", ret.String())
|
||||
for _, item := range ret.ImportImageTasks {
|
||||
if *item.Status == "completed" {
|
||||
return *item.ImageId, nil
|
||||
}
|
||||
}
|
||||
time.Sleep(1 * time.Minute)
|
||||
}
|
||||
|
||||
return task.ImageId, fmt.Errorf("uploadImage uncompleted: %s", task)
|
||||
|
||||
}
|
||||
|
||||
func (self *SStoragecache) downloadImage(userCred mcclient.TokenCredential, imageId string, extId string) (jsonutils.JSONObject, error) {
|
||||
// aws 导出镜像限制比较多。https://docs.aws.amazon.com/zh_cn/vm-import/latest/userguide/vmexport.html
|
||||
bucketName := "imgcache-onecloud"
|
||||
if err := self.region.checkBucket(bucketName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
instanceId, err := self.region.GetInstanceIdByImageId(extId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
task, err := self.region.ExportImage(instanceId, imageId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
taskParams := &ec2.DescribeExportTasksInput{}
|
||||
taskParams.SetExportTaskIds([]*string{&task.TaskId})
|
||||
if err := self.region.ec2Client.WaitUntilExportTaskCompleted(taskParams); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s3Client, err := self.region.getS3Client()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
i := &s3.GetObjectInput{}
|
||||
i.SetBucket(bucketName)
|
||||
i.SetKey(fmt.Sprintf("%s.%s", task.TaskId, "ova"))
|
||||
ret, err := s3Client.GetObject(i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s := auth.GetAdminSession(options.Options.Region, "")
|
||||
params := jsonutils.Marshal(map[string]string{"image_id": imageId, "disk-format": "raw"})
|
||||
if result, err := modules.Images.Upload(s, params, ret.Body, IntVal(ret.ContentLength)); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) CheckBucket(bucketName string) error {
|
||||
return self.checkBucket(bucketName)
|
||||
}
|
||||
|
||||
func (self *SRegion) checkBucket(bucketName string) error {
|
||||
exists, err := self.IsBucketExist(bucketName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !exists {
|
||||
return fmt.Errorf("bucket %s not found", bucketName)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (self *SRegion) IsBucketExist(bucketName string) (bool, error) {
|
||||
s3Client, err := self.getS3Client()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
params := &s3.ListBucketsInput{}
|
||||
ret, err := s3Client.ListBuckets(params)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, bucket := range ret.Buckets {
|
||||
if bucket.Name != nil && *bucket.Name == bucketName {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetARNPartition() string {
|
||||
// https://docs.amazonaws.cn/general/latest/gr/aws-arns-and-namespaces.html?id=docs_gateway
|
||||
// https://github.com/aws/chalice/issues/777
|
||||
// https://github.com/aws/chalice/issues/792
|
||||
/*
|
||||
I assume this is because the ARN format is slightly different for China.
|
||||
In general, ARNs follow the pattern arn:partition:service:region:account-id:resource,
|
||||
where partition is aws for most of the world and aws-cn for China.
|
||||
It looks like the more common "arn:aws" is currently hardcoded in quite a few places.
|
||||
*/
|
||||
if strings.HasPrefix(self.RegionId, "cn-") {
|
||||
return "aws-cn"
|
||||
} else {
|
||||
return "aws"
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) initVmimportRole() error {
|
||||
/*需要api access token 具备iam Full access权限*/
|
||||
iamClient, err := self.getIamClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// search role vmimport
|
||||
rolename := "vmimport"
|
||||
ret, _ := iamClient.GetRole(&iam.GetRoleInput{RoleName: &rolename})
|
||||
// todo: 这里得区分是not found.还是其他错误
|
||||
if ret.Role != nil && ret.Role.RoleId != nil {
|
||||
return nil
|
||||
} else {
|
||||
// create it
|
||||
roleDoc := `{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": { "Service": "vmie.amazonaws.com" },
|
||||
"Action": "sts:AssumeRole",
|
||||
"Condition": {
|
||||
"StringEquals":{
|
||||
"sts:Externalid": "vmimport"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}`
|
||||
params := &iam.CreateRoleInput{}
|
||||
params.SetDescription("vmimport role for image import")
|
||||
params.SetRoleName(rolename)
|
||||
params.SetAssumeRolePolicyDocument(roleDoc)
|
||||
|
||||
_, err = iamClient.CreateRole(params)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) initVmimportRolePolicy() error {
|
||||
/*需要api access token 具备iam Full access权限*/
|
||||
iamClient, err := self.getIamClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
partition := self.GetARNPartition()
|
||||
roleName := "vmimport"
|
||||
policyName := "vmimport"
|
||||
ret, err := iamClient.GetRolePolicy(&iam.GetRolePolicyInput{RoleName: &roleName, PolicyName: &policyName})
|
||||
// todo: 这里得区分是not found.还是其他错误.
|
||||
if ret.PolicyName != nil {
|
||||
return nil
|
||||
} else {
|
||||
rolePolicy := `{
|
||||
"Version":"2012-10-17",
|
||||
"Statement":[
|
||||
{
|
||||
"Effect":"Allow",
|
||||
"Action":[
|
||||
"s3:GetBucketLocation",
|
||||
"s3:GetObject",
|
||||
"s3:ListBucket"
|
||||
],
|
||||
"Resource":[
|
||||
"arn:%[1]s:s3:::%[2]s",
|
||||
"arn:%[1]s:s3:::%[2]s/*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Effect":"Allow",
|
||||
"Action":[
|
||||
"ec2:ModifySnapshotAttribute",
|
||||
"ec2:CopySnapshot",
|
||||
"ec2:RegisterImage",
|
||||
"ec2:Describe*"
|
||||
],
|
||||
"Resource":"*"
|
||||
}
|
||||
]
|
||||
}`
|
||||
params := &iam.PutRolePolicyInput{}
|
||||
params.SetPolicyDocument(fmt.Sprintf(rolePolicy, partition, "imgcache-onecloud"))
|
||||
params.SetPolicyName(policyName)
|
||||
params.SetRoleName(roleName)
|
||||
_, err = iamClient.PutRolePolicy(params)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) initVmimportBucket() error {
|
||||
bucketName := "imgcache-onecloud"
|
||||
// todo: "imgcache-onecloud" 使用常量
|
||||
exists, err := self.IsBucketExist("imgcache-onecloud")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if exists {
|
||||
return nil
|
||||
}
|
||||
|
||||
s3Client, err := self.getS3Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = s3Client.CreateBucket(&s3.CreateBucketInput{Bucket: &bucketName})
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SRegion) initVmimport() error {
|
||||
if err := self.initVmimportRole(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := self.initVmimportRolePolicy(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := self.initVmimportBucket(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) createIImage(snapshotId, imageName, imageDesc string) (string, error) {
|
||||
params := &ec2.CreateImageInput{}
|
||||
params.SetDescription(imageDesc)
|
||||
params.SetName(imageName)
|
||||
block := &ec2.BlockDeviceMapping{}
|
||||
block.SetDeviceName("/dev/sda1")
|
||||
ebs := &ec2.EbsBlockDevice{}
|
||||
ebs.SetSnapshotId(snapshotId)
|
||||
ebs.SetDeleteOnTermination(true)
|
||||
block.SetEbs(ebs)
|
||||
blockList := []*ec2.BlockDeviceMapping{block}
|
||||
params.SetBlockDeviceMappings(blockList)
|
||||
|
||||
ret, err := self.ec2Client.CreateImage(params)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return *ret.ImageId, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) getStoragecache() *SStoragecache {
|
||||
if self.storageCache == nil {
|
||||
self.storageCache = &SStoragecache{region: self}
|
||||
}
|
||||
return self.storageCache
|
||||
}
|
||||
@@ -0,0 +1,426 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"reflect"
|
||||
"strings"
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
)
|
||||
|
||||
type portRange struct {
|
||||
Start int64
|
||||
End int64
|
||||
}
|
||||
|
||||
type TagSpec struct {
|
||||
ResourceType string // "customer-gateway"|"dedicated-host"|"dhcp-options"|"image"|"instance"|"internet-gateway"|"network-acl"|"network-interface"|"reserved-instances"|"route-table"|"snapshot"|"spot-instances-request"|"subnet"|"security-group"|"volume"|"vpc"|"vpn-connection"|"vpn-gateway"
|
||||
Tags map[string]string
|
||||
}
|
||||
|
||||
func (self *TagSpec) LoadingEc2Tags(tags []*ec2.Tag) {
|
||||
for _, tag := range tags {
|
||||
if tag.Key != nil && tag.Value != nil {
|
||||
self.SetTag(*tag.Key, *tag.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *TagSpec) GetTagSpecifications() (*ec2.TagSpecification, error) {
|
||||
if self.ResourceType == "" {
|
||||
return nil, fmt.Errorf("ResourceType should not be empty")
|
||||
}
|
||||
|
||||
spec := &ec2.TagSpecification{ResourceType: &self.ResourceType}
|
||||
tags := []*ec2.Tag{}
|
||||
for k, v := range self.Tags {
|
||||
if len(v) > 255 {
|
||||
return nil, fmt.Errorf("%s value length should less than 255", k)
|
||||
}
|
||||
|
||||
tag := &ec2.Tag{}
|
||||
tag.SetKey(k)
|
||||
tag.SetValue(v)
|
||||
tags = append(tags, tag)
|
||||
}
|
||||
|
||||
spec.SetTags(tags)
|
||||
return spec, nil
|
||||
}
|
||||
|
||||
func (self *TagSpec) SetTag(k, v string) {
|
||||
if self.Tags == nil {
|
||||
self.Tags = make(map[string]string)
|
||||
}
|
||||
self.Tags[k] = v
|
||||
}
|
||||
|
||||
func (self *TagSpec) SetNameTag(v string) {
|
||||
self.SetTag("Name", v)
|
||||
}
|
||||
|
||||
func (self *TagSpec) SetDescTag(v string) {
|
||||
self.SetTag("Description", v)
|
||||
}
|
||||
|
||||
func (self *TagSpec) GetTag(k string) (string, error) {
|
||||
v, ok := self.Tags[k]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("%s not found", k)
|
||||
}
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// 找不到的情况下返回传入的默认值
|
||||
func (self *TagSpec) GetTagWithDefault(k, Default string) string {
|
||||
v, ok := self.Tags[k]
|
||||
if !ok {
|
||||
return Default
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
func (self *TagSpec) GetNameTag() string {
|
||||
return self.GetTagWithDefault("Name", "")
|
||||
}
|
||||
|
||||
func (self *TagSpec) GetDescTag() string {
|
||||
return self.GetTagWithDefault("Description", "")
|
||||
}
|
||||
|
||||
func AppendFilter(filters []*ec2.Filter, name string, values []string) []*ec2.Filter {
|
||||
f := &ec2.Filter{}
|
||||
v := make([]*string, len(values))
|
||||
for _, value := range values {
|
||||
v = append(v, &value)
|
||||
}
|
||||
|
||||
f.SetName(name)
|
||||
f.SetValues(v)
|
||||
return append(filters, f)
|
||||
}
|
||||
|
||||
func AppendSingleValueFilter(filters []*ec2.Filter, name string, value string) []*ec2.Filter {
|
||||
f := &ec2.Filter{}
|
||||
f.SetName(name)
|
||||
f.SetValues([]*string{&value})
|
||||
return append(filters, f)
|
||||
}
|
||||
|
||||
func ConvertedList(list []string) []*string {
|
||||
result := make([]*string, 0)
|
||||
for _, item := range list {
|
||||
if len(item) > 0 {
|
||||
result = append(result, &item)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func ConvertedPointList(list []*string) []string {
|
||||
result := make([]string, len(list))
|
||||
for _, item := range list {
|
||||
if item != nil {
|
||||
result = append(result, *item)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func StrVal(s *string) string {
|
||||
if s != nil {
|
||||
return *s
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func IntVal(s *int64) int64 {
|
||||
if s != nil {
|
||||
return *s
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func isAwsPermissionAllPorts(p ec2.IpPermission) bool {
|
||||
if p.FromPort == nil || p.ToPort == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// 全部端口范围: TCP/UDP (0,65535) 其他:(-1,-1)
|
||||
if (*p.IpProtocol == "tcp" || *p.IpProtocol == "udp") && *p.FromPort == 0 && *p.ToPort == 65535 {
|
||||
return true
|
||||
} else if *p.FromPort == -1 && *p.ToPort == -1 {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func awsProtocolToYunion(p ec2.IpPermission) string {
|
||||
if p.IpProtocol != nil && *p.IpProtocol == "-1" {
|
||||
return secrules.PROTO_ANY
|
||||
} else {
|
||||
return *p.IpProtocol
|
||||
}
|
||||
}
|
||||
|
||||
func yunionProtocolToAws(r secrules.SecurityRule) string {
|
||||
if r.Protocol == secrules.PROTO_ANY {
|
||||
return "-1"
|
||||
} else {
|
||||
return r.Protocol
|
||||
}
|
||||
}
|
||||
|
||||
func isYunionRuleAllPorts(r secrules.SecurityRule) bool {
|
||||
// 全部端口范围: TCP/UDP (0,65535) 其他:(-1,-1)
|
||||
if (r.Protocol == "tcp" || r.Protocol == "udp") && r.PortStart == 0 && r.PortEnd == 65535 {
|
||||
return true
|
||||
} else if r.PortStart == -1 && r.PortEnd == -1 {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func yunionPortRangeToAws(r secrules.SecurityRule) []portRange {
|
||||
// port 0 / -1 都代表所有端口
|
||||
portranges := []portRange{}
|
||||
if len(r.Ports) == 0 {
|
||||
var start, end = 0, 0
|
||||
if r.PortStart <= 0 {
|
||||
if r.Protocol == "tcp" || r.Protocol == "udp" {
|
||||
start = 0
|
||||
} else {
|
||||
start = -1
|
||||
}
|
||||
} else {
|
||||
start = r.PortStart
|
||||
}
|
||||
|
||||
if r.PortEnd <= 0 {
|
||||
if r.Protocol == "tcp" || r.Protocol == "udp" {
|
||||
end = 65535
|
||||
} else {
|
||||
end = -1
|
||||
}
|
||||
} else {
|
||||
end = r.PortEnd
|
||||
}
|
||||
|
||||
portranges = append(portranges, portRange{int64(start), int64(end)})
|
||||
}
|
||||
|
||||
for _, port := range r.Ports {
|
||||
if port <= 0 && (r.Protocol == "tcp" || r.Protocol == "udp") {
|
||||
portranges = append(portranges, portRange{0, 65535})
|
||||
} else if port <= 0 {
|
||||
portranges = append(portranges, portRange{-1, -1})
|
||||
} else {
|
||||
portranges = append(portranges, portRange{int64(port), int64(port)})
|
||||
}
|
||||
}
|
||||
|
||||
return portranges
|
||||
}
|
||||
|
||||
// Security Rule Transform
|
||||
func AwsIpPermissionToYunion(direction secrules.TSecurityRuleDirection, p ec2.IpPermission) ([]secrules.SecurityRule, error) {
|
||||
|
||||
if len(p.UserIdGroupPairs) > 0 {
|
||||
return nil, fmt.Errorf("AwsIpPermissionToYunion not supported aws rule: UserIdGroupPairs specified")
|
||||
}
|
||||
|
||||
if len(p.PrefixListIds) > 0 {
|
||||
return nil, fmt.Errorf("AwsIpPermissionToYunion not supported aws rule: PrefixListIds specified")
|
||||
}
|
||||
|
||||
if len(p.Ipv6Ranges) > 0 {
|
||||
log.Debugf("AwsIpPermissionToYunion ignored IPV6 rule: %s", p.Ipv6Ranges)
|
||||
}
|
||||
|
||||
rules := []secrules.SecurityRule{}
|
||||
isAllPorts := isAwsPermissionAllPorts(p)
|
||||
protocol := awsProtocolToYunion(p)
|
||||
for _, ip := range p.IpRanges {
|
||||
_, ipNet, err := net.ParseCIDR(*ip.CidrIp)
|
||||
if err != nil {
|
||||
log.Errorf("ParseCIDR failed, ignored IPV4 rule: %s", *ip.CidrIp)
|
||||
continue
|
||||
}
|
||||
|
||||
var rule secrules.SecurityRule
|
||||
if isAllPorts {
|
||||
rule = secrules.SecurityRule{
|
||||
Action: secrules.SecurityRuleAllow,
|
||||
IPNet: ipNet,
|
||||
Protocol: protocol,
|
||||
Direction: direction,
|
||||
Priority: 1,
|
||||
Description: StrVal(ip.Description),
|
||||
}
|
||||
} else {
|
||||
rule = secrules.SecurityRule{
|
||||
Action: secrules.SecurityRuleAllow,
|
||||
IPNet: ipNet,
|
||||
Protocol: protocol,
|
||||
Direction: direction,
|
||||
Priority: 1,
|
||||
Description: StrVal(ip.Description),
|
||||
}
|
||||
|
||||
if p.FromPort != nil {
|
||||
rule.PortStart = int(*p.FromPort)
|
||||
}
|
||||
|
||||
if p.ToPort != nil {
|
||||
rule.PortEnd = int(*p.ToPort)
|
||||
}
|
||||
}
|
||||
|
||||
rules = append(rules, rule)
|
||||
|
||||
}
|
||||
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func YunionSecRuleToAws(rule secrules.SecurityRule) ([]*ec2.IpPermission, error) {
|
||||
if rule.Action == secrules.SecurityRuleDeny {
|
||||
return nil, fmt.Errorf("YunionSecRuleToAws ignored aws not supported deny rule")
|
||||
}
|
||||
|
||||
iprange := rule.IPNet.String()
|
||||
if iprange == "<nil>" {
|
||||
return nil, fmt.Errorf("YunionSecRuleToAws ignored ipnet should not be empty")
|
||||
}
|
||||
ipranges := []*ec2.IpRange{}
|
||||
ipranges = append(ipranges, &ec2.IpRange{CidrIp: &iprange, Description: &rule.Description})
|
||||
|
||||
portranges := yunionPortRangeToAws(rule)
|
||||
protocol := yunionProtocolToAws(rule)
|
||||
permissions := []*ec2.IpPermission{}
|
||||
for _, port := range portranges {
|
||||
permission := ec2.IpPermission{
|
||||
FromPort: &port.Start,
|
||||
IpProtocol: &protocol,
|
||||
IpRanges: ipranges,
|
||||
ToPort: &port.End,
|
||||
}
|
||||
|
||||
permissions = append(permissions, &permission)
|
||||
}
|
||||
|
||||
return permissions, nil
|
||||
}
|
||||
|
||||
// fill a pointer struct with zero value.
|
||||
func FillZero(i interface{}) error {
|
||||
V := reflect.Indirect(reflect.ValueOf(i))
|
||||
|
||||
if !V.CanSet() {
|
||||
return fmt.Errorf("input is not addressable: %#v", i)
|
||||
}
|
||||
|
||||
if V.Kind() != reflect.Struct {
|
||||
return fmt.Errorf("only accept struct type")
|
||||
}
|
||||
|
||||
for i := 0; i < V.NumField(); i++ {
|
||||
field := V.Field(i)
|
||||
|
||||
if field.Kind() == reflect.Ptr && field.IsNil() {
|
||||
if field.CanSet() {
|
||||
field.Set(reflect.New(field.Type().Elem()))
|
||||
}
|
||||
}
|
||||
|
||||
vField := reflect.Indirect(field)
|
||||
switch vField.Kind() {
|
||||
case reflect.Map:
|
||||
vField.Set(reflect.MakeMap(vField.Type()))
|
||||
case reflect.Struct:
|
||||
if field.CanInterface() {
|
||||
err := FillZero(field.Interface())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func NextDeviceName(curDeviceNames []string) (string, error) {
|
||||
currents := []string{}
|
||||
for _, item := range curDeviceNames {
|
||||
currents = append(currents, strings.ToLower(item))
|
||||
}
|
||||
|
||||
for i := 0; i < 25; i++ {
|
||||
device := fmt.Sprintf("/dev/sd%s", string(98+i))
|
||||
found := false
|
||||
for _, item := range currents {
|
||||
if strings.HasPrefix(item, device) {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
return device, nil
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < 25; i++ {
|
||||
device := fmt.Sprintf("/dev/vxd%s", string(98+i))
|
||||
found := false
|
||||
for _, item := range currents {
|
||||
if !strings.HasPrefix(item, device) {
|
||||
return device, nil
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
return device, nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("disk devicename out of index, current deivces: %s", currents)
|
||||
}
|
||||
|
||||
// fetch tags
|
||||
func FetchTags(client *ec2.EC2, resourceId string) (*jsonutils.JSONDict, error) {
|
||||
result := jsonutils.NewDict()
|
||||
params := &ec2.DescribeTagsInput{}
|
||||
filters := []*ec2.Filter{}
|
||||
if len(resourceId) == 0 {
|
||||
return result, fmt.Errorf("resource id should not be empty")
|
||||
}
|
||||
// todo: add resource type filter
|
||||
filters = AppendSingleValueFilter(filters, "resource-id", resourceId)
|
||||
params.SetFilters(filters)
|
||||
|
||||
ret, err := client.DescribeTags(params)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
for _, tag := range ret.Tags {
|
||||
if tag.Key != nil && tag.Value != nil {
|
||||
result.Set(*tag.Key, jsonutils.NewString(*tag.Value))
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"strings"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
)
|
||||
|
||||
type SUserCIDRs struct {
|
||||
UserCidr []string
|
||||
}
|
||||
|
||||
type SVpc struct {
|
||||
region *SRegion
|
||||
|
||||
iwires []cloudprovider.ICloudWire
|
||||
secgroups []cloudprovider.ICloudSecurityGroup
|
||||
|
||||
RegionId string
|
||||
VpcId string
|
||||
VpcName string
|
||||
CidrBlock string
|
||||
IsDefault bool
|
||||
Status string
|
||||
Tags map[string]string // 名称、描述等
|
||||
}
|
||||
|
||||
func (self *SVpc) addWire(wire *SWire) {
|
||||
if self.iwires == nil {
|
||||
self.iwires = make([]cloudprovider.ICloudWire, 0)
|
||||
}
|
||||
self.iwires = append(self.iwires, wire)
|
||||
}
|
||||
|
||||
func (self *SVpc) GetId() string {
|
||||
return self.VpcId
|
||||
}
|
||||
|
||||
func (self *SVpc) GetName() string {
|
||||
if len(self.VpcName) > 0 {
|
||||
return self.VpcName
|
||||
}
|
||||
return self.VpcId
|
||||
}
|
||||
|
||||
func (self *SVpc) GetGlobalId() string {
|
||||
return self.VpcId
|
||||
}
|
||||
|
||||
func (self *SVpc) GetStatus() string {
|
||||
return strings.ToLower(self.Status)
|
||||
}
|
||||
|
||||
func (self *SVpc) Refresh() error {
|
||||
new, err := self.region.getVpc(self.VpcId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(self, new)
|
||||
}
|
||||
|
||||
func (self *SVpc) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SVpc) GetMetadata() *jsonutils.JSONDict {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SVpc) GetRegion() cloudprovider.ICloudRegion {
|
||||
return self.region
|
||||
}
|
||||
|
||||
func (self *SVpc) GetIsDefault() bool {
|
||||
return self.IsDefault
|
||||
}
|
||||
|
||||
func (self *SVpc) GetCidrBlock() string {
|
||||
return self.CidrBlock
|
||||
}
|
||||
|
||||
func (self *SVpc) GetIWires() ([]cloudprovider.ICloudWire, error) {
|
||||
if self.iwires == nil {
|
||||
err := self.fetchNetworks()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return self.iwires, nil
|
||||
}
|
||||
|
||||
func (self *SVpc) GetISecurityGroups() ([]cloudprovider.ICloudSecurityGroup, error) {
|
||||
if self.secgroups == nil {
|
||||
err := self.fetchSecurityGroups()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return self.secgroups, nil
|
||||
}
|
||||
|
||||
func (self *SVpc) GetManagerId() string {
|
||||
return self.region.client.providerId
|
||||
}
|
||||
|
||||
func (self *SVpc) Delete() error {
|
||||
err := self.fetchSecurityGroups()
|
||||
if err != nil {
|
||||
log.Errorf("fetchSecurityGroup for VPC delete fail %s", err)
|
||||
return err
|
||||
}
|
||||
for i := 0; i < len(self.secgroups); i += 1 {
|
||||
secgroup := self.secgroups[i].(*SSecurityGroup)
|
||||
err := self.region.deleteSecurityGroup(secgroup.SecurityGroupId)
|
||||
if err != nil {
|
||||
log.Errorf("deleteSecurityGroup for VPC delete fail %s", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return self.region.DeleteVpc(self.VpcId)
|
||||
}
|
||||
|
||||
func (self *SVpc) GetIWireById(wireId string) (cloudprovider.ICloudWire, error) {
|
||||
if self.iwires == nil {
|
||||
err := self.fetchNetworks()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(self.iwires); i += 1 {
|
||||
if self.iwires[i].GetGlobalId() == wireId {
|
||||
return self.iwires[i], nil
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SVpc) SyncSecurityGroup(secgroupId string, name string, rules []secrules.SecurityRule) (string, error) {
|
||||
secgrpId := ""
|
||||
if secgroup, err := self.region.getSecurityGroupByTag(self.VpcId, secgroupId); err != nil {
|
||||
// 名称为default的安全组与aws默认安全组名冲突
|
||||
if strings.ToLower(name) == "default" {
|
||||
name = fmt.Sprintf("%s-%s", self.VpcId, name)
|
||||
}
|
||||
|
||||
desc := fmt.Sprintf("security group %s for vpc %s", name, self.VpcId)
|
||||
if secgrpId, err = self.region.createSecurityGroup(self.VpcId, name, secgroupId, desc); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
//addRules
|
||||
log.Debugf("Add Rules for %s : %s", secgrpId, rules)
|
||||
for _, rule := range rules {
|
||||
if err := self.region.addSecurityGroupRule(secgrpId, &rule); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//syncRules
|
||||
secgrpId = secgroup.SecurityGroupId
|
||||
log.Debugf("Sync Rules for %s", secgroup.GetName())
|
||||
if secgroup.GetName() != name {
|
||||
if err := self.region.modifySecurityGroup(secgrpId, name, ""); err != nil {
|
||||
log.Errorf("Change SecurityGroup name to %s failed: %v", name, err)
|
||||
}
|
||||
}
|
||||
self.region.syncSecgroupRules(secgrpId, rules)
|
||||
}
|
||||
return secgrpId, nil
|
||||
}
|
||||
|
||||
func (self *SVpc) getWireByZoneId(zoneId string) *SWire {
|
||||
for i := 0; i < len(self.iwires); i += 1 {
|
||||
wire := self.iwires[i].(*SWire)
|
||||
if wire.zone.ZoneId == zoneId {
|
||||
return wire
|
||||
}
|
||||
}
|
||||
|
||||
zone, err := self.region.getZoneById(zoneId)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return &SWire{
|
||||
zone: zone,
|
||||
vpc: self,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SVpc) fetchNetworks() error {
|
||||
networks, _, err := self.region.GetNetwroks(nil, self.VpcId, 0, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := 0; i < len(networks); i += 1 {
|
||||
wire := self.getWireByZoneId(networks[i].ZoneId)
|
||||
networks[i].wire = wire
|
||||
wire.addNetwork(&networks[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SVpc) revokeSecurityGroup(secgroupId string, instanceId string, keep bool) error {
|
||||
return self.region.revokeSecurityGroup(secgroupId, instanceId, keep)
|
||||
}
|
||||
|
||||
func (self *SVpc) assignSecurityGroup(secgroupId string, instanceId string) error {
|
||||
return self.region.assignSecurityGroup(secgroupId, instanceId)
|
||||
}
|
||||
|
||||
func (self *SVpc) fetchSecurityGroups() error {
|
||||
secgroups, _, err := self.region.GetSecurityGroups(self.VpcId, "", 0, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.secgroups = make([]cloudprovider.ICloudSecurityGroup, len(secgroups))
|
||||
for i := 0; i < len(secgroups); i++ {
|
||||
secgroups[i].vpc = self
|
||||
self.secgroups[i] = &secgroups[i]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) getVpc(vpcId string) (*SVpc, error) {
|
||||
vpcs, total, err := self.GetVpcs([]string{vpcId}, 0, 1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if total != 1 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
vpcs[0].region = self
|
||||
return &vpcs[0], nil
|
||||
}
|
||||
|
||||
func (self *SRegion) revokeSecurityGroup(secgroupId, instanceId string, keep bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) assignSecurityGroup(secgroupId, instanceId string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) deleteSecurityGroup(secGrpId string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) DeleteVpc(vpcId string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetVpcs(vpcId []string, offset int, limit int) ([]SVpc, int, error) {
|
||||
params := &ec2.DescribeVpcsInput{}
|
||||
if len(vpcId) > 0 {
|
||||
params.SetVpcIds(ConvertedList(vpcId))
|
||||
}
|
||||
ret, err := self.ec2Client.DescribeVpcs(params)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
vpcs := []SVpc{}
|
||||
for _, item := range ret.Vpcs {
|
||||
if err := FillZero(item); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
vpcs = append(vpcs, SVpc{
|
||||
region: self,
|
||||
// secgroups: nil,
|
||||
RegionId: self.RegionId,
|
||||
VpcId: *item.VpcId,
|
||||
VpcName: *item.VpcId,
|
||||
CidrBlock: *item.CidrBlock,
|
||||
IsDefault: *item.IsDefault,
|
||||
Status: *item.State,
|
||||
// Tags: *item.Tags,
|
||||
})
|
||||
}
|
||||
|
||||
return vpcs, len(vpcs), nil
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
type SWire struct {
|
||||
zone *SZone
|
||||
vpc *SVpc
|
||||
|
||||
inetworks []cloudprovider.ICloudNetwork
|
||||
}
|
||||
|
||||
func (self *SWire) GetId() string {
|
||||
return fmt.Sprintf("%s-%s", self.vpc.GetId(), self.zone.GetId())
|
||||
}
|
||||
|
||||
func (self *SWire) GetName() string {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
func (self *SWire) GetGlobalId() string {
|
||||
return fmt.Sprintf("%s-%s", self.vpc.GetGlobalId(), self.zone.GetGlobalId())
|
||||
}
|
||||
|
||||
func (self *SWire) GetStatus() string {
|
||||
return "available"
|
||||
}
|
||||
|
||||
func (self *SWire) Refresh() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SWire) IsEmulated() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SWire) GetMetadata() *jsonutils.JSONDict {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SWire) GetIVpc() cloudprovider.ICloudVpc {
|
||||
return self.vpc
|
||||
}
|
||||
|
||||
func (self *SWire) GetIZone() cloudprovider.ICloudZone {
|
||||
return self.zone
|
||||
}
|
||||
|
||||
func (self *SWire) GetINetworks() ([]cloudprovider.ICloudNetwork, error) {
|
||||
if self.inetworks == nil {
|
||||
err := self.vpc.fetchNetworks()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return self.inetworks, nil
|
||||
}
|
||||
|
||||
func (self *SWire) GetBandwidth() int {
|
||||
return 10000
|
||||
}
|
||||
|
||||
func (self *SWire) GetINetworkById(netid string) (cloudprovider.ICloudNetwork, error) {
|
||||
networks, err := self.GetINetworks()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(networks); i += 1 {
|
||||
if networks[i].GetGlobalId() == netid {
|
||||
return networks[i], nil
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SWire) CreateINetwork(name string, cidr string, desc string) (cloudprovider.ICloudNetwork, error) {
|
||||
networkId, err := self.zone.region.createNetwork(self.zone.ZoneId, self.vpc.VpcId, name, cidr, desc)
|
||||
if err != nil {
|
||||
log.Errorf("createNetwork error %s", err)
|
||||
return nil, err
|
||||
}
|
||||
self.inetworks = nil
|
||||
network := self.getNetworkById(networkId)
|
||||
if network == nil {
|
||||
log.Errorf("cannot find network after create????")
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return network, nil
|
||||
}
|
||||
|
||||
func (self *SWire) getNetworkById(networkId string) *SNetwork {
|
||||
networks, err := self.GetINetworks()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
log.Debugf("search for networks %d", len(networks))
|
||||
for i := 0; i < len(networks); i += 1 {
|
||||
log.Debugf("search %s", networks[i].GetName())
|
||||
network := networks[i]
|
||||
if network.GetId() == networkId {
|
||||
return network.(*SNetwork)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SWire) addNetwork(network *SNetwork) {
|
||||
if self.inetworks == nil {
|
||||
self.inetworks = make([]cloudprovider.ICloudNetwork, 0)
|
||||
}
|
||||
find := false
|
||||
for i := 0; i < len(self.inetworks); i += 1 {
|
||||
if self.inetworks[i].GetId() == network.NetworkId {
|
||||
find = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !find {
|
||||
self.inetworks = append(self.inetworks, network)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
var StorageTypes = []string{
|
||||
models.STORAGE_GP2_SSD,
|
||||
models.STORAGE_IO1_SSD,
|
||||
models.STORAGE_ST1_HDD,
|
||||
models.STORAGE_SC1_SSD,
|
||||
models.STORAGE_STANDARD_SSD,
|
||||
}
|
||||
|
||||
type SZone struct {
|
||||
region *SRegion
|
||||
host *SHost
|
||||
|
||||
iwires []cloudprovider.ICloudWire
|
||||
istorages []cloudprovider.ICloudStorage
|
||||
|
||||
ZoneId string // 沿用阿里云ZoneId,对应Aws ZoneName
|
||||
LocalName string
|
||||
State string
|
||||
|
||||
/* 支持的磁盘种类集合 */
|
||||
storageTypes []string
|
||||
}
|
||||
|
||||
func (self *SZone) addWire(wire *SWire) {
|
||||
if self.iwires == nil {
|
||||
self.iwires = make([]cloudprovider.ICloudWire, 0)
|
||||
}
|
||||
self.iwires = append(self.iwires, wire)
|
||||
}
|
||||
|
||||
func (self *SZone) getHost() *SHost {
|
||||
if self.host == nil {
|
||||
self.host = &SHost{zone: self}
|
||||
}
|
||||
return self.host
|
||||
}
|
||||
|
||||
func (self *SZone) getStorageType() {
|
||||
if len(self.storageTypes) == 0 {
|
||||
self.storageTypes = StorageTypes
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SZone) fetchStorages() error {
|
||||
self.getStorageType()
|
||||
self.istorages = make([]cloudprovider.ICloudStorage, len(self.storageTypes))
|
||||
|
||||
for i, sc := range self.storageTypes {
|
||||
storage := SStorage{zone: self, storageType: sc}
|
||||
self.istorages[i] = &storage
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SZone) GetIWires() ([]cloudprovider.ICloudWire, error) {
|
||||
return self.iwires, nil
|
||||
}
|
||||
|
||||
func (self *SZone) getNetworkById(networkId string) *SNetwork {
|
||||
log.Debugf("Search in wires %d", len(self.iwires))
|
||||
for i := 0; i < len(self.iwires); i += 1 {
|
||||
log.Debugf("Search in wire %s", self.iwires[i].GetName())
|
||||
wire := self.iwires[i].(*SWire)
|
||||
net := wire.getNetworkById(networkId)
|
||||
if net != nil {
|
||||
return net
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SZone) GetId() string {
|
||||
return self.ZoneId
|
||||
}
|
||||
|
||||
func (self *SZone) GetName() string {
|
||||
return fmt.Sprintf("%s %s", CLOUD_PROVIDER_AWS_CN, self.LocalName)
|
||||
}
|
||||
|
||||
func (self *SZone) GetGlobalId() string {
|
||||
return fmt.Sprintf("%s/%s", self.region.GetGlobalId(), self.ZoneId)
|
||||
}
|
||||
|
||||
func (self *SZone) GetStatus() string {
|
||||
if self.State == "unavailable" {
|
||||
return models.ZONE_SOLDOUT
|
||||
} else {
|
||||
return models.ZONE_ENABLE
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SZone) Refresh() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SZone) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SZone) GetMetadata() *jsonutils.JSONDict {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SZone) GetIRegion() cloudprovider.ICloudRegion {
|
||||
return self.region
|
||||
}
|
||||
|
||||
func (self *SZone) GetIHosts() ([]cloudprovider.ICloudHost, error) {
|
||||
return []cloudprovider.ICloudHost{self.getHost()}, nil
|
||||
}
|
||||
|
||||
func (self *SZone) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
|
||||
host := self.getHost()
|
||||
if host.GetGlobalId() == id {
|
||||
return host, nil
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SZone) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
|
||||
if self.istorages == nil {
|
||||
self.fetchStorages()
|
||||
}
|
||||
return self.istorages, nil
|
||||
}
|
||||
|
||||
func (self *SZone) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
|
||||
if self.istorages == nil {
|
||||
self.fetchStorages()
|
||||
}
|
||||
for i := 0; i < len(self.istorages); i += 1 {
|
||||
if self.istorages[i].GetGlobalId() == id {
|
||||
return self.istorages[i], nil
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SZone) getStorageByCategory(category string) (*SStorage, error) {
|
||||
storages, err := self.GetIStorages()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(storages); i += 1 {
|
||||
storage := storages[i].(*SStorage)
|
||||
if storage.storageType == category {
|
||||
return storage, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("No such storage %s", category)
|
||||
}
|
||||
|
||||
func (self *SRegion) getZoneById(id string) (*SZone, error) {
|
||||
izones, err := self.GetIZones()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(izones); i += 1 {
|
||||
zone := izones[i].(*SZone)
|
||||
if zone.ZoneId == id {
|
||||
return zone, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("no such zone %s", id)
|
||||
}
|
||||
@@ -214,6 +214,11 @@ func (self *SRegion) doDeleteVM(instanceId string) error {
|
||||
|
||||
func (self *SInstance) GetMetadata() *jsonutils.JSONDict {
|
||||
data := jsonutils.NewDict()
|
||||
tags := jsonutils.NewDict()
|
||||
for k, v := range self.Tags {
|
||||
tags.Set(k, jsonutils.NewString(v))
|
||||
}
|
||||
data.Update(tags)
|
||||
if osDistribution := self.Properties.StorageProfile.ImageReference.Publisher; len(osDistribution) > 0 {
|
||||
data.Add(jsonutils.NewString(osDistribution), "os_distribution")
|
||||
}
|
||||
|
||||
Generated
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
package credentials
|
||||
|
||||
type BaseCredential struct {
|
||||
AccessKeyId string
|
||||
AccessKeySecret string
|
||||
}
|
||||
Generated
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
package credentials
|
||||
|
||||
type EcsInstanceCredential struct {
|
||||
RoleName string
|
||||
}
|
||||
Generated
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
package credentials
|
||||
|
||||
type KeyPairCredential struct {
|
||||
PrivateKey string
|
||||
PublicKeyId string
|
||||
SessionExpiration int
|
||||
}
|
||||
Generated
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
package credentials
|
||||
|
||||
type StsAssumeRoleCredential struct {
|
||||
AccessKeyId string
|
||||
AccessKeySecret string
|
||||
RoleArn string
|
||||
RoleSessionName string
|
||||
RoleSessionExpiration int
|
||||
}
|
||||
Generated
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
package credentials
|
||||
|
||||
type StsCredential struct {
|
||||
AccessKeyId string
|
||||
AccessKeySecret string
|
||||
AccessKeyStsToken string
|
||||
}
|
||||
Generated
Vendored
-34
@@ -1,34 +0,0 @@
|
||||
package credentials
|
||||
|
||||
// Deprecated: Use AccessKeyCredential in this package instead.
|
||||
type BaseCredential struct {
|
||||
AccessKeyId string
|
||||
AccessKeySecret string
|
||||
}
|
||||
|
||||
type AccessKeyCredential struct {
|
||||
AccessKeyId string
|
||||
AccessKeySecret string
|
||||
}
|
||||
|
||||
// Deprecated: Use NewAccessKeyCredential in this package instead.
|
||||
func NewBaseCredential(accessKeyId, accessKeySecret string) *BaseCredential {
|
||||
return &BaseCredential{
|
||||
AccessKeyId: accessKeyId,
|
||||
AccessKeySecret: accessKeySecret,
|
||||
}
|
||||
}
|
||||
|
||||
func (baseCred *BaseCredential) ToAccessKeyCredential() *AccessKeyCredential {
|
||||
return &AccessKeyCredential{
|
||||
AccessKeyId: baseCred.AccessKeyId,
|
||||
AccessKeySecret: baseCred.AccessKeySecret,
|
||||
}
|
||||
}
|
||||
|
||||
func NewAccessKeyCredential(accessKeyId, accessKeySecret string) *AccessKeyCredential {
|
||||
return &AccessKeyCredential{
|
||||
AccessKeyId: accessKeyId,
|
||||
AccessKeySecret: accessKeySecret,
|
||||
}
|
||||
}
|
||||
Generated
Vendored
-29
@@ -1,29 +0,0 @@
|
||||
package credentials
|
||||
|
||||
// Deprecated: Use EcsRamRoleCredential in this package instead.
|
||||
type StsRoleNameOnEcsCredential struct {
|
||||
RoleName string
|
||||
}
|
||||
|
||||
// Deprecated: Use NewEcsRamRoleCredential in this package instead.
|
||||
func NewStsRoleNameOnEcsCredential(roleName string) *StsRoleNameOnEcsCredential {
|
||||
return &StsRoleNameOnEcsCredential{
|
||||
RoleName: roleName,
|
||||
}
|
||||
}
|
||||
|
||||
func (oldCred *StsRoleNameOnEcsCredential) ToEcsRamRoleCredential() *EcsRamRoleCredential {
|
||||
return &EcsRamRoleCredential{
|
||||
RoleName: oldCred.RoleName,
|
||||
}
|
||||
}
|
||||
|
||||
type EcsRamRoleCredential struct {
|
||||
RoleName string
|
||||
}
|
||||
|
||||
func NewEcsRamRoleCredential(roleName string) *EcsRamRoleCredential {
|
||||
return &EcsRamRoleCredential{
|
||||
RoleName: roleName,
|
||||
}
|
||||
}
|
||||
Generated
Vendored
-15
@@ -1,15 +0,0 @@
|
||||
package credentials
|
||||
|
||||
type RsaKeyPairCredential struct {
|
||||
PrivateKey string
|
||||
PublicKeyId string
|
||||
SessionExpiration int
|
||||
}
|
||||
|
||||
func NewRsaKeyPairCredential(privateKey, publicKeyId string, sessionExpiration int) *RsaKeyPairCredential {
|
||||
return &RsaKeyPairCredential{
|
||||
PrivateKey: privateKey,
|
||||
PublicKeyId: publicKeyId,
|
||||
SessionExpiration: sessionExpiration,
|
||||
}
|
||||
}
|
||||
Generated
Vendored
-15
@@ -1,15 +0,0 @@
|
||||
package credentials
|
||||
|
||||
type StsTokenCredential struct {
|
||||
AccessKeyId string
|
||||
AccessKeySecret string
|
||||
AccessKeyStsToken string
|
||||
}
|
||||
|
||||
func NewStsTokenCredential(accessKeyId, accessKeySecret, accessKeyStsToken string) *StsTokenCredential {
|
||||
return &StsTokenCredential{
|
||||
AccessKeyId: accessKeyId,
|
||||
AccessKeySecret: accessKeySecret,
|
||||
AccessKeyStsToken: accessKeyStsToken,
|
||||
}
|
||||
}
|
||||
Generated
Vendored
-49
@@ -1,49 +0,0 @@
|
||||
package credentials
|
||||
|
||||
// Deprecated: Use RamRoleArnCredential in this package instead.
|
||||
type StsRoleArnCredential struct {
|
||||
AccessKeyId string
|
||||
AccessKeySecret string
|
||||
RoleArn string
|
||||
RoleSessionName string
|
||||
RoleSessionExpiration int
|
||||
}
|
||||
|
||||
type RamRoleArnCredential struct {
|
||||
AccessKeyId string
|
||||
AccessKeySecret string
|
||||
RoleArn string
|
||||
RoleSessionName string
|
||||
RoleSessionExpiration int
|
||||
}
|
||||
|
||||
// Deprecated: Use RamRoleArnCredential in this package instead.
|
||||
func NewStsRoleArnCredential(accessKeyId, accessKeySecret, roleArn, roleSessionName string, roleSessionExpiration int) *StsRoleArnCredential {
|
||||
return &StsRoleArnCredential{
|
||||
AccessKeyId: accessKeyId,
|
||||
AccessKeySecret: accessKeySecret,
|
||||
RoleArn: roleArn,
|
||||
RoleSessionName: roleSessionName,
|
||||
RoleSessionExpiration: roleSessionExpiration,
|
||||
}
|
||||
}
|
||||
|
||||
func (oldCred *StsRoleArnCredential) ToRamRoleArnCredential() *RamRoleArnCredential {
|
||||
return &RamRoleArnCredential{
|
||||
AccessKeyId: oldCred.AccessKeyId,
|
||||
AccessKeySecret: oldCred.AccessKeySecret,
|
||||
RoleArn: oldCred.RoleArn,
|
||||
RoleSessionName: oldCred.RoleSessionName,
|
||||
RoleSessionExpiration: oldCred.RoleSessionExpiration,
|
||||
}
|
||||
}
|
||||
|
||||
func NewRamRoleArnCredential(accessKeyId, accessKeySecret, roleArn, roleSessionName string, roleSessionExpiration int) *RamRoleArnCredential {
|
||||
return &RamRoleArnCredential{
|
||||
AccessKeyId: accessKeyId,
|
||||
AccessKeySecret: accessKeySecret,
|
||||
RoleArn: roleArn,
|
||||
RoleSessionName: roleSessionName,
|
||||
RoleSessionExpiration: roleSessionExpiration,
|
||||
}
|
||||
}
|
||||
+7
-21
@@ -22,41 +22,27 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func signRoaRequest(request requests.AcsRequest, signer Signer, regionId string) (err error) {
|
||||
func signRoaRequest(request requests.AcsRequest, signer Signer, regionId string) {
|
||||
completeROASignParams(request, signer, regionId)
|
||||
stringToSign := buildRoaStringToSign(request)
|
||||
request.SetStringToSign(stringToSign)
|
||||
signature := signer.Sign(stringToSign, "")
|
||||
accessKeyId, err := signer.GetAccessKeyId()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
request.GetHeaders()["Authorization"] = "acs " + accessKeyId + ":" + signature
|
||||
|
||||
return
|
||||
request.GetHeaders()["Authorization"] = "acs " + signer.GetAccessKeyId() + ":" + signature
|
||||
}
|
||||
|
||||
func completeROASignParams(request requests.AcsRequest, signer Signer, regionId string) {
|
||||
headerParams := request.GetHeaders()
|
||||
|
||||
// complete query params
|
||||
queryParams := request.GetQueryParams()
|
||||
//if _, ok := queryParams["RegionId"]; !ok {
|
||||
// queryParams["RegionId"] = regionId
|
||||
//}
|
||||
if _, ok := queryParams["RegionId"]; !ok {
|
||||
queryParams["RegionId"] = regionId
|
||||
}
|
||||
if extraParam := signer.GetExtraParam(); extraParam != nil {
|
||||
for key, value := range extraParam {
|
||||
if key == "SecurityToken" {
|
||||
headerParams["x-acs-security-token"] = value
|
||||
continue
|
||||
}
|
||||
|
||||
queryParams[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
// complete header params
|
||||
headerParams := request.GetHeaders()
|
||||
headerParams["Date"] = utils.GetTimeInFormatRFC2616()
|
||||
headerParams["x-acs-signature-method"] = signer.GetName()
|
||||
headerParams["x-acs-signature-version"] = signer.GetVersion()
|
||||
@@ -108,7 +94,7 @@ func buildRoaStringToSign(request requests.AcsRequest) (stringToSign string) {
|
||||
}
|
||||
|
||||
// append query params
|
||||
stringToSignBuilder.WriteString(request.BuildQueries())
|
||||
stringToSignBuilder.WriteString(request.GetQueries())
|
||||
stringToSign = stringToSignBuilder.String()
|
||||
return
|
||||
}
|
||||
|
||||
+4
-20
@@ -22,24 +22,14 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func signRpcRequest(request requests.AcsRequest, signer Signer, regionId string) (err error) {
|
||||
err = completeRpcSignParams(request, signer, regionId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// remove while retry
|
||||
if _, containsSign := request.GetQueryParams()["Signature"]; containsSign {
|
||||
delete(request.GetQueryParams(), "Signature")
|
||||
}
|
||||
func signRpcRequest(request requests.AcsRequest, signer Signer, regionId string) {
|
||||
completeRpcSignParams(request, signer, regionId)
|
||||
stringToSign := buildRpcStringToSign(request)
|
||||
request.SetStringToSign(stringToSign)
|
||||
signature := signer.Sign(stringToSign, "&")
|
||||
request.GetQueryParams()["Signature"] = signature
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func completeRpcSignParams(request requests.AcsRequest, signer Signer, regionId string) (err error) {
|
||||
func completeRpcSignParams(request requests.AcsRequest, signer Signer, regionId string) {
|
||||
queryParams := request.GetQueryParams()
|
||||
queryParams["Version"] = request.GetVersion()
|
||||
queryParams["Action"] = request.GetActionName()
|
||||
@@ -49,11 +39,7 @@ func completeRpcSignParams(request requests.AcsRequest, signer Signer, regionId
|
||||
queryParams["SignatureType"] = signer.GetType()
|
||||
queryParams["SignatureVersion"] = signer.GetVersion()
|
||||
queryParams["SignatureNonce"] = utils.GetUUIDV4()
|
||||
queryParams["AccessKeyId"], err = signer.GetAccessKeyId()
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
queryParams["AccessKeyId"] = signer.GetAccessKeyId()
|
||||
|
||||
if _, contains := queryParams["RegionId"]; !contains {
|
||||
queryParams["RegionId"] = regionId
|
||||
@@ -67,8 +53,6 @@ func completeRpcSignParams(request requests.AcsRequest, signer Signer, regionId
|
||||
request.GetHeaders()["Content-Type"] = requests.Form
|
||||
formString := utils.GetUrlFormedMap(request.GetFormParams())
|
||||
request.SetContent([]byte(formString))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func buildRpcStringToSign(request requests.AcsRequest) (stringToSign string) {
|
||||
|
||||
+15
-28
@@ -28,7 +28,7 @@ type Signer interface {
|
||||
GetName() string
|
||||
GetType() string
|
||||
GetVersion() string
|
||||
GetAccessKeyId() (string, error)
|
||||
GetAccessKeyId() string
|
||||
GetExtraParam() map[string]string
|
||||
Sign(stringToSign, secretSuffix string) string
|
||||
Shutdown()
|
||||
@@ -36,42 +36,29 @@ type Signer interface {
|
||||
|
||||
func NewSignerWithCredential(credential Credential, commonApi func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error)) (signer Signer, err error) {
|
||||
switch instance := credential.(type) {
|
||||
case *credentials.AccessKeyCredential:
|
||||
case *credentials.BaseCredential:
|
||||
{
|
||||
signer, err = signers.NewAccessKeySigner(instance)
|
||||
signer, err = signers.NewSignerV1(instance)
|
||||
}
|
||||
case *credentials.StsTokenCredential:
|
||||
case *credentials.StsCredential:
|
||||
{
|
||||
signer, err = signers.NewStsTokenSigner(instance)
|
||||
signer, err = signers.NewSignerSts(instance)
|
||||
}
|
||||
|
||||
case *credentials.RamRoleArnCredential:
|
||||
case *credentials.StsAssumeRoleCredential:
|
||||
{
|
||||
signer, err = signers.NewRamRoleArnSigner(instance, commonApi)
|
||||
signer, err = signers.NewSignerStsAssumeRole(instance, commonApi)
|
||||
}
|
||||
case *credentials.RsaKeyPairCredential:
|
||||
case *credentials.KeyPairCredential:
|
||||
{
|
||||
signer, err = signers.NewSignerKeyPair(instance, commonApi)
|
||||
}
|
||||
case *credentials.EcsRamRoleCredential:
|
||||
case *credentials.EcsInstanceCredential:
|
||||
{
|
||||
signer, err = signers.NewEcsRamRoleSigner(instance, commonApi)
|
||||
}
|
||||
case *credentials.BaseCredential: // deprecated user interface
|
||||
{
|
||||
signer, err = signers.NewAccessKeySigner(instance.ToAccessKeyCredential())
|
||||
}
|
||||
case *credentials.StsRoleArnCredential: // deprecated user interface
|
||||
{
|
||||
signer, err = signers.NewRamRoleArnSigner(instance.ToRamRoleArnCredential(), commonApi)
|
||||
}
|
||||
case *credentials.StsRoleNameOnEcsCredential: // deprecated user interface
|
||||
{
|
||||
signer, err = signers.NewEcsRamRoleSigner(instance.ToEcsRamRoleCredential(), commonApi)
|
||||
signer, err = signers.NewSignereEcsInstance(instance, commonApi)
|
||||
}
|
||||
default:
|
||||
message := fmt.Sprintf(errors.UnsupportedCredentialErrorMessage, reflect.TypeOf(credential))
|
||||
err = errors.NewClientError(errors.UnsupportedCredentialErrorCode, message, nil)
|
||||
message := fmt.Sprintf(errors.UnsupportedCredentialMessage, reflect.TypeOf(credential))
|
||||
err = errors.NewClientError(errors.UnsupportedCredentialCode, message, nil)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -84,11 +71,11 @@ func Sign(request requests.AcsRequest, signer Signer, regionId string) (err erro
|
||||
}
|
||||
case requests.RPC:
|
||||
{
|
||||
err = signRpcRequest(request, signer, regionId)
|
||||
signRpcRequest(request, signer, regionId)
|
||||
}
|
||||
default:
|
||||
message := fmt.Sprintf(errors.UnknownRequestTypeErrorMessage, reflect.TypeOf(request))
|
||||
err = errors.NewClientError(errors.UnknownRequestTypeErrorCode, message, nil)
|
||||
message := fmt.Sprintf(errors.UnknownRequestTypeMessage, reflect.TypeOf(request))
|
||||
err = errors.NewClientError(errors.UnknownRequestTypeCode, message, nil)
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
+1
-1
@@ -58,6 +58,6 @@ func Sha256WithRsa(source, secret string) string {
|
||||
}
|
||||
|
||||
signedString := base64.StdEncoding.EncodeToString(signature)
|
||||
//fmt.Printf("Encoded: %v\n", signedString)
|
||||
fmt.Printf("Encoded: %v\n", signedString)
|
||||
return signedString
|
||||
}
|
||||
|
||||
Generated
Vendored
-7
@@ -1,7 +0,0 @@
|
||||
package signers
|
||||
|
||||
type SessionCredential struct {
|
||||
AccessKeyId string
|
||||
AccessKeySecret string
|
||||
StsToken string
|
||||
}
|
||||
+29
-31
@@ -26,15 +26,15 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type EcsRamRoleSigner struct {
|
||||
type SignerEcsInstance struct {
|
||||
*credentialUpdater
|
||||
sessionCredential *SessionCredential
|
||||
credential *credentials.EcsRamRoleCredential
|
||||
sessionCredential *sessionCredential
|
||||
credential *credentials.EcsInstanceCredential
|
||||
commonApi func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error)
|
||||
}
|
||||
|
||||
func NewEcsRamRoleSigner(credential *credentials.EcsRamRoleCredential, commonApi func(*requests.CommonRequest, interface{}) (response *responses.CommonResponse, err error)) (signer *EcsRamRoleSigner, err error) {
|
||||
signer = &EcsRamRoleSigner{
|
||||
func NewSignereEcsInstance(credential *credentials.EcsInstanceCredential, commonApi func(*requests.CommonRequest, interface{}) (response *responses.CommonResponse, err error)) (signer *SignerEcsInstance, err error) {
|
||||
signer = &SignerEcsInstance{
|
||||
credential: credential,
|
||||
commonApi: commonApi,
|
||||
}
|
||||
@@ -49,49 +49,49 @@ func NewEcsRamRoleSigner(credential *credentials.EcsRamRoleCredential, commonApi
|
||||
return
|
||||
}
|
||||
|
||||
func (*EcsRamRoleSigner) GetName() string {
|
||||
func (*SignerEcsInstance) GetName() string {
|
||||
return "HMAC-SHA1"
|
||||
}
|
||||
|
||||
func (*EcsRamRoleSigner) GetType() string {
|
||||
func (*SignerEcsInstance) GetType() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (*EcsRamRoleSigner) GetVersion() string {
|
||||
func (*SignerEcsInstance) GetVersion() string {
|
||||
return "1.0"
|
||||
}
|
||||
|
||||
func (signer *EcsRamRoleSigner) GetAccessKeyId() (accessKeyId string, err error) {
|
||||
func (signer *SignerEcsInstance) GetAccessKeyId() string {
|
||||
if signer.sessionCredential == nil || signer.needUpdateCredential() {
|
||||
err = signer.updateCredential()
|
||||
signer.updateCredential()
|
||||
}
|
||||
if err != nil && (signer.sessionCredential == nil || len(signer.sessionCredential.AccessKeyId) <= 0) {
|
||||
return "", err
|
||||
if len(signer.sessionCredential.accessKeyId) <= 0 {
|
||||
return ""
|
||||
}
|
||||
return signer.sessionCredential.AccessKeyId, nil
|
||||
return signer.sessionCredential.accessKeyId
|
||||
}
|
||||
|
||||
func (signer *EcsRamRoleSigner) GetExtraParam() map[string]string {
|
||||
func (signer *SignerEcsInstance) GetExtraParam() map[string]string {
|
||||
if signer.sessionCredential == nil {
|
||||
return make(map[string]string)
|
||||
}
|
||||
if len(signer.sessionCredential.StsToken) <= 0 {
|
||||
if len(signer.sessionCredential.securityToken) <= 0 {
|
||||
return make(map[string]string)
|
||||
}
|
||||
return map[string]string{"SecurityToken": signer.sessionCredential.StsToken}
|
||||
return map[string]string{"SecurityToken": signer.sessionCredential.securityToken}
|
||||
}
|
||||
|
||||
func (signer *EcsRamRoleSigner) Sign(stringToSign, secretSuffix string) string {
|
||||
secret := signer.sessionCredential.AccessKeyId + secretSuffix
|
||||
func (signer *SignerEcsInstance) Sign(stringToSign, secretSuffix string) string {
|
||||
secret := signer.sessionCredential.accessKeySecret + secretSuffix
|
||||
return ShaHmac1(stringToSign, secret)
|
||||
}
|
||||
|
||||
func (signer *EcsRamRoleSigner) buildCommonRequest() (request *requests.CommonRequest, err error) {
|
||||
func (signer *SignerEcsInstance) buildCommonRequest() (request *requests.CommonRequest, err error) {
|
||||
request = requests.NewCommonRequest()
|
||||
return
|
||||
}
|
||||
|
||||
func (signer *EcsRamRoleSigner) refreshApi(request *requests.CommonRequest) (response *responses.CommonResponse, err error) {
|
||||
func (signer *SignerEcsInstance) refreshApi(request *requests.CommonRequest) (response *responses.CommonResponse, err error) {
|
||||
requestUrl := "http://100.100.100.200/latest/meta-data/ram/security-credentials/" + signer.credential.RoleName
|
||||
httpRequest, err := http.NewRequest(requests.GET, requestUrl, strings.NewReader(""))
|
||||
if err != nil {
|
||||
@@ -111,7 +111,7 @@ func (signer *EcsRamRoleSigner) refreshApi(request *requests.CommonRequest) (res
|
||||
return
|
||||
}
|
||||
|
||||
func (signer *EcsRamRoleSigner) refreshCredential(response *responses.CommonResponse) (err error) {
|
||||
func (signer *SignerEcsInstance) refreshCredential(response *responses.CommonResponse) (err error) {
|
||||
if response.GetHttpStatus() != http.StatusOK {
|
||||
fmt.Println("refresh Ecs sts token err, httpStatus: " + string(response.GetHttpStatus()) + ", message = " + response.GetHttpContentString())
|
||||
return
|
||||
@@ -152,24 +152,22 @@ func (signer *EcsRamRoleSigner) refreshCredential(response *responses.CommonResp
|
||||
return
|
||||
}
|
||||
if accessKeyId == nil || accessKeySecret == nil || securityToken == nil {
|
||||
return
|
||||
if signer.sessionCredential == nil {
|
||||
panic("refresh Ecs sts token failed, accessKeyId, accessKeySecret or securityToken is null")
|
||||
}
|
||||
}
|
||||
|
||||
expirationTime, err := time.Parse("2006-01-02T15:04:05Z", expiration.(string))
|
||||
signer.credentialExpiration = int(expirationTime.Unix() - time.Now().Unix())
|
||||
signer.sessionCredential = &SessionCredential{
|
||||
AccessKeyId: accessKeyId.(string),
|
||||
AccessKeySecret: accessKeySecret.(string),
|
||||
StsToken: securityToken.(string),
|
||||
signer.sessionCredential = &sessionCredential{
|
||||
accessKeyId: accessKeyId.(string),
|
||||
accessKeySecret: accessKeySecret.(string),
|
||||
securityToken: securityToken.(string),
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (signer *EcsRamRoleSigner) GetSessionCredential() *SessionCredential {
|
||||
return signer.sessionCredential
|
||||
}
|
||||
|
||||
func (signer *EcsRamRoleSigner) Shutdown() {
|
||||
func (signer *SignerEcsInstance) Shutdown() {
|
||||
|
||||
}
|
||||
Generated
Vendored
+27
-17
@@ -28,12 +28,17 @@ import (
|
||||
|
||||
type SignerKeyPair struct {
|
||||
*credentialUpdater
|
||||
sessionCredential *SessionCredential
|
||||
credential *credentials.RsaKeyPairCredential
|
||||
sessionCredential *SessionAkCredential
|
||||
credential *credentials.KeyPairCredential
|
||||
commonApi func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error)
|
||||
}
|
||||
|
||||
func NewSignerKeyPair(credential *credentials.RsaKeyPairCredential, commonApi func(*requests.CommonRequest, interface{}) (response *responses.CommonResponse, err error)) (signer *SignerKeyPair, err error) {
|
||||
type SessionAkCredential struct {
|
||||
accessKeyId string
|
||||
accessKeySecret string
|
||||
}
|
||||
|
||||
func NewSignerKeyPair(credential *credentials.KeyPairCredential, commonApi func(*requests.CommonRequest, interface{}) (response *responses.CommonResponse, err error)) (signer *SignerKeyPair, err error) {
|
||||
signer = &SignerKeyPair{
|
||||
credential: credential,
|
||||
commonApi: commonApi,
|
||||
@@ -50,7 +55,7 @@ func NewSignerKeyPair(credential *credentials.RsaKeyPairCredential, commonApi fu
|
||||
if credential.SessionExpiration >= 900 && credential.SessionExpiration <= 3600 {
|
||||
signer.credentialExpiration = credential.SessionExpiration
|
||||
} else {
|
||||
err = errors.NewClientError(errors.InvalidParamErrorCode, "Key Pair session duration should be in the range of 15min - 1Hr", nil)
|
||||
err = errors.NewClientError(errors.InvalidParamCode, "Key Pair session duration should be in the range of 15min - 1Hr", nil)
|
||||
}
|
||||
} else {
|
||||
signer.credentialExpiration = defaultDurationSeconds
|
||||
@@ -70,28 +75,28 @@ func (*SignerKeyPair) GetVersion() string {
|
||||
return "1.0"
|
||||
}
|
||||
|
||||
func (signer *SignerKeyPair) GetAccessKeyId() (accessKeyId string, err error) {
|
||||
func (signer *SignerKeyPair) GetAccessKeyId() string {
|
||||
if signer.sessionCredential == nil || signer.needUpdateCredential() {
|
||||
err = signer.updateCredential()
|
||||
signer.updateCredential()
|
||||
}
|
||||
if err != nil && (signer.sessionCredential == nil || len(signer.sessionCredential.AccessKeyId) <= 0) {
|
||||
return "", err
|
||||
if signer.sessionCredential == nil || len(signer.sessionCredential.accessKeyId) <= 0 {
|
||||
return ""
|
||||
}
|
||||
return signer.sessionCredential.AccessKeyId, err
|
||||
return signer.sessionCredential.accessKeyId
|
||||
}
|
||||
|
||||
func (signer *SignerKeyPair) GetExtraParam() map[string]string {
|
||||
if signer.sessionCredential == nil || signer.needUpdateCredential() {
|
||||
signer.updateCredential()
|
||||
}
|
||||
if signer.sessionCredential == nil || len(signer.sessionCredential.AccessKeyId) <= 0 {
|
||||
if signer.sessionCredential == nil || len(signer.sessionCredential.accessKeyId) <= 0 {
|
||||
return make(map[string]string)
|
||||
}
|
||||
return make(map[string]string)
|
||||
}
|
||||
|
||||
func (signer *SignerKeyPair) Sign(stringToSign, secretSuffix string) string {
|
||||
secret := signer.sessionCredential.AccessKeyId + secretSuffix
|
||||
secret := signer.sessionCredential.accessKeySecret + secretSuffix
|
||||
return ShaHmac1(stringToSign, secret)
|
||||
}
|
||||
|
||||
@@ -113,8 +118,11 @@ func (signerKeyPair *SignerKeyPair) refreshApi(request *requests.CommonRequest)
|
||||
|
||||
func (signer *SignerKeyPair) refreshCredential(response *responses.CommonResponse) (err error) {
|
||||
if response.GetHttpStatus() != http.StatusOK {
|
||||
message := "refresh session AccessKey failed"
|
||||
err = errors.NewServerError(response.GetHttpStatus(), response.GetHttpContentString(), message)
|
||||
message := "refresh session AccessKey failed, message = " + response.GetHttpContentString()
|
||||
err = errors.NewServerError(response.GetHttpStatus(), response.GetOriginHttpResponse().Status, message)
|
||||
if signer.sessionCredential == nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
var data interface{}
|
||||
@@ -134,11 +142,13 @@ func (signer *SignerKeyPair) refreshCredential(response *responses.CommonRespons
|
||||
return
|
||||
}
|
||||
if accessKeyId == nil || accessKeySecret == nil {
|
||||
return
|
||||
if signer.sessionCredential == nil {
|
||||
panic("refresh KeyPair, accessKeyId or accessKeySecret is null")
|
||||
}
|
||||
}
|
||||
signer.sessionCredential = &SessionCredential{
|
||||
AccessKeyId: accessKeyId.(string),
|
||||
AccessKeySecret: accessKeySecret.(string),
|
||||
signer.sessionCredential = &SessionAkCredential{
|
||||
accessKeyId: accessKeyId.(string),
|
||||
accessKeySecret: accessKeySecret.(string),
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
Generated
Vendored
+12
-12
@@ -18,41 +18,41 @@ import (
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
|
||||
)
|
||||
|
||||
type StsTokenSigner struct {
|
||||
credential *credentials.StsTokenCredential
|
||||
type SignerSts struct {
|
||||
credential *credentials.StsCredential
|
||||
}
|
||||
|
||||
func NewStsTokenSigner(credential *credentials.StsTokenCredential) (*StsTokenSigner, error) {
|
||||
return &StsTokenSigner{
|
||||
func NewSignerSts(credential *credentials.StsCredential) (*SignerSts, error) {
|
||||
return &SignerSts{
|
||||
credential: credential,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (*StsTokenSigner) GetName() string {
|
||||
func (*SignerSts) GetName() string {
|
||||
return "HMAC-SHA1"
|
||||
}
|
||||
|
||||
func (*StsTokenSigner) GetType() string {
|
||||
func (*SignerSts) GetType() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (*StsTokenSigner) GetVersion() string {
|
||||
func (*SignerSts) GetVersion() string {
|
||||
return "1.0"
|
||||
}
|
||||
|
||||
func (signer *StsTokenSigner) GetAccessKeyId() (accessKeyId string, err error) {
|
||||
return signer.credential.AccessKeyId, nil
|
||||
func (signer *SignerSts) GetAccessKeyId() string {
|
||||
return signer.credential.AccessKeyId
|
||||
}
|
||||
|
||||
func (signer *StsTokenSigner) GetExtraParam() map[string]string {
|
||||
func (signer *SignerSts) GetExtraParam() map[string]string {
|
||||
return map[string]string{"SecurityToken": signer.credential.AccessKeyStsToken}
|
||||
}
|
||||
|
||||
func (signer *StsTokenSigner) Sign(stringToSign, secretSuffix string) string {
|
||||
func (signer *SignerSts) Sign(stringToSign, secretSuffix string) string {
|
||||
secret := signer.credential.AccessKeySecret + secretSuffix
|
||||
return ShaHmac1(stringToSign, secret)
|
||||
}
|
||||
|
||||
func (signer *StsTokenSigner) Shutdown() {
|
||||
func (signer *SignerSts) Shutdown() {
|
||||
|
||||
}
|
||||
+53
-46
@@ -31,16 +31,22 @@ const (
|
||||
defaultDurationSeconds = 3600
|
||||
)
|
||||
|
||||
type RamRoleArnSigner struct {
|
||||
type SignerStsAssumeRole struct {
|
||||
*credentialUpdater
|
||||
roleSessionName string
|
||||
sessionCredential *SessionCredential
|
||||
credential *credentials.RamRoleArnCredential
|
||||
sessionCredential *sessionCredential
|
||||
credential *credentials.StsAssumeRoleCredential
|
||||
commonApi func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error)
|
||||
}
|
||||
|
||||
func NewRamRoleArnSigner(credential *credentials.RamRoleArnCredential, commonApi func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error)) (signer *RamRoleArnSigner, err error) {
|
||||
signer = &RamRoleArnSigner{
|
||||
type sessionCredential struct {
|
||||
accessKeyId string
|
||||
accessKeySecret string
|
||||
securityToken string
|
||||
}
|
||||
|
||||
func NewSignerStsAssumeRole(credential *credentials.StsAssumeRoleCredential, commonApi func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error)) (signer *SignerStsAssumeRole, err error) {
|
||||
signer = &SignerStsAssumeRole{
|
||||
credential: credential,
|
||||
commonApi: commonApi,
|
||||
}
|
||||
@@ -58,10 +64,10 @@ func NewRamRoleArnSigner(credential *credentials.RamRoleArnCredential, commonApi
|
||||
signer.roleSessionName = "aliyun-go-sdk-" + strconv.FormatInt(time.Now().UnixNano()/1000, 10)
|
||||
}
|
||||
if credential.RoleSessionExpiration > 0 {
|
||||
if credential.RoleSessionExpiration >= 900 && credential.RoleSessionExpiration <= 3600 {
|
||||
if credential.RoleSessionExpiration > 900 && credential.RoleSessionExpiration < 3600 {
|
||||
signer.credentialExpiration = credential.RoleSessionExpiration
|
||||
} else {
|
||||
err = errors.NewClientError(errors.InvalidParamErrorCode, "Assume Role session duration should be in the range of 15min - 1Hr", nil)
|
||||
err = errors.NewClientError(errors.InvalidParamCode, "Assume Role session duration should be in the range of 15min - 1Hr", nil)
|
||||
}
|
||||
} else {
|
||||
signer.credentialExpiration = defaultDurationSeconds
|
||||
@@ -69,44 +75,44 @@ func NewRamRoleArnSigner(credential *credentials.RamRoleArnCredential, commonApi
|
||||
return
|
||||
}
|
||||
|
||||
func (*RamRoleArnSigner) GetName() string {
|
||||
func (*SignerStsAssumeRole) GetName() string {
|
||||
return "HMAC-SHA1"
|
||||
}
|
||||
|
||||
func (*RamRoleArnSigner) GetType() string {
|
||||
func (*SignerStsAssumeRole) GetType() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (*RamRoleArnSigner) GetVersion() string {
|
||||
func (*SignerStsAssumeRole) GetVersion() string {
|
||||
return "1.0"
|
||||
}
|
||||
|
||||
func (signer *RamRoleArnSigner) GetAccessKeyId() (accessKeyId string, err error) {
|
||||
if signer.sessionCredential == nil || signer.needUpdateCredential() {
|
||||
err = signer.updateCredential()
|
||||
}
|
||||
if err != nil && (signer.sessionCredential == nil || len(signer.sessionCredential.AccessKeyId) <= 0) {
|
||||
return "", err
|
||||
}
|
||||
return signer.sessionCredential.AccessKeyId, nil
|
||||
}
|
||||
|
||||
func (signer *RamRoleArnSigner) GetExtraParam() map[string]string {
|
||||
func (signer *SignerStsAssumeRole) GetAccessKeyId() string {
|
||||
if signer.sessionCredential == nil || signer.needUpdateCredential() {
|
||||
signer.updateCredential()
|
||||
}
|
||||
if signer.sessionCredential == nil || len(signer.sessionCredential.StsToken) <= 0 {
|
||||
return make(map[string]string)
|
||||
if signer.sessionCredential == nil || len(signer.sessionCredential.accessKeyId) <= 0 {
|
||||
return ""
|
||||
}
|
||||
return map[string]string{"SecurityToken": signer.sessionCredential.StsToken}
|
||||
return signer.sessionCredential.accessKeyId
|
||||
}
|
||||
|
||||
func (signer *RamRoleArnSigner) Sign(stringToSign, secretSuffix string) string {
|
||||
secret := signer.sessionCredential.AccessKeySecret + secretSuffix
|
||||
func (signer *SignerStsAssumeRole) GetExtraParam() map[string]string {
|
||||
if signer.sessionCredential == nil || signer.needUpdateCredential() {
|
||||
signer.updateCredential()
|
||||
}
|
||||
if signer.sessionCredential == nil || len(signer.sessionCredential.securityToken) <= 0 {
|
||||
return make(map[string]string)
|
||||
}
|
||||
return map[string]string{"SecurityToken": signer.sessionCredential.securityToken}
|
||||
}
|
||||
|
||||
func (signer *SignerStsAssumeRole) Sign(stringToSign, secretSuffix string) string {
|
||||
secret := signer.sessionCredential.accessKeySecret + secretSuffix
|
||||
return ShaHmac1(stringToSign, secret)
|
||||
}
|
||||
|
||||
func (signer *RamRoleArnSigner) buildCommonRequest() (request *requests.CommonRequest, err error) {
|
||||
func (signer *SignerStsAssumeRole) buildCommonRequest() (request *requests.CommonRequest, err error) {
|
||||
request = requests.NewCommonRequest()
|
||||
request.Product = "Sts"
|
||||
request.Version = "2015-04-01"
|
||||
@@ -118,19 +124,22 @@ func (signer *RamRoleArnSigner) buildCommonRequest() (request *requests.CommonRe
|
||||
return
|
||||
}
|
||||
|
||||
func (signer *RamRoleArnSigner) refreshApi(request *requests.CommonRequest) (response *responses.CommonResponse, err error) {
|
||||
credential := &credentials.AccessKeyCredential{
|
||||
AccessKeyId: signer.credential.AccessKeyId,
|
||||
AccessKeySecret: signer.credential.AccessKeySecret,
|
||||
func (signerStsAssumeRole *SignerStsAssumeRole) refreshApi(request *requests.CommonRequest) (response *responses.CommonResponse, err error) {
|
||||
credential := &credentials.BaseCredential{
|
||||
AccessKeyId: signerStsAssumeRole.credential.AccessKeyId,
|
||||
AccessKeySecret: signerStsAssumeRole.credential.AccessKeySecret,
|
||||
}
|
||||
signerV1, err := NewAccessKeySigner(credential)
|
||||
return signer.commonApi(request, signerV1)
|
||||
signerV1, err := NewSignerV1(credential)
|
||||
return signerStsAssumeRole.commonApi(request, signerV1)
|
||||
}
|
||||
|
||||
func (signer *RamRoleArnSigner) refreshCredential(response *responses.CommonResponse) (err error) {
|
||||
func (signer *SignerStsAssumeRole) refreshCredential(response *responses.CommonResponse) (err error) {
|
||||
if response.GetHttpStatus() != http.StatusOK {
|
||||
message := "refresh session token failed"
|
||||
err = errors.NewServerError(response.GetHttpStatus(), response.GetHttpContentString(), message)
|
||||
message := "refresh session token failed, message = " + response.GetHttpContentString()
|
||||
err = errors.NewServerError(response.GetHttpStatus(), response.GetOriginHttpResponse().Status, message)
|
||||
if signer.sessionCredential == nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
var data interface{}
|
||||
@@ -155,20 +164,18 @@ func (signer *RamRoleArnSigner) refreshCredential(response *responses.CommonResp
|
||||
return
|
||||
}
|
||||
if accessKeyId == nil || accessKeySecret == nil || securityToken == nil {
|
||||
return
|
||||
if signer.sessionCredential == nil {
|
||||
panic("refresh session token failed, accessKeyId, accessKeySecret or securityToken is null")
|
||||
}
|
||||
}
|
||||
signer.sessionCredential = &SessionCredential{
|
||||
AccessKeyId: accessKeyId.(string),
|
||||
AccessKeySecret: accessKeySecret.(string),
|
||||
StsToken: securityToken.(string),
|
||||
signer.sessionCredential = &sessionCredential{
|
||||
accessKeyId: accessKeyId.(string),
|
||||
accessKeySecret: accessKeySecret.(string),
|
||||
securityToken: securityToken.(string),
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (signer *RamRoleArnSigner) GetSessionCredential() *SessionCredential {
|
||||
return signer.sessionCredential
|
||||
}
|
||||
|
||||
func (signer *RamRoleArnSigner) Shutdown() {
|
||||
func (signer *SignerStsAssumeRole) Shutdown() {
|
||||
|
||||
}
|
||||
Generated
Vendored
+12
-12
@@ -18,41 +18,41 @@ import (
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
|
||||
)
|
||||
|
||||
type AccessKeySigner struct {
|
||||
credential *credentials.AccessKeyCredential
|
||||
type SignerV1 struct {
|
||||
credential *credentials.BaseCredential
|
||||
}
|
||||
|
||||
func (signer *AccessKeySigner) GetExtraParam() map[string]string {
|
||||
func (signer *SignerV1) GetExtraParam() map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewAccessKeySigner(credential *credentials.AccessKeyCredential) (*AccessKeySigner, error) {
|
||||
return &AccessKeySigner{
|
||||
func NewSignerV1(credential *credentials.BaseCredential) (*SignerV1, error) {
|
||||
return &SignerV1{
|
||||
credential: credential,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (*AccessKeySigner) GetName() string {
|
||||
func (*SignerV1) GetName() string {
|
||||
return "HMAC-SHA1"
|
||||
}
|
||||
|
||||
func (*AccessKeySigner) GetType() string {
|
||||
func (*SignerV1) GetType() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (*AccessKeySigner) GetVersion() string {
|
||||
func (*SignerV1) GetVersion() string {
|
||||
return "1.0"
|
||||
}
|
||||
|
||||
func (signer *AccessKeySigner) GetAccessKeyId() (accessKeyId string, err error) {
|
||||
return signer.credential.AccessKeyId, nil
|
||||
func (signer *SignerV1) GetAccessKeyId() string {
|
||||
return signer.credential.AccessKeyId
|
||||
}
|
||||
|
||||
func (signer *AccessKeySigner) Sign(stringToSign, secretSuffix string) string {
|
||||
func (signer *SignerV1) Sign(stringToSign, secretSuffix string) string {
|
||||
secret := signer.credential.AccessKeySecret + secretSuffix
|
||||
return ShaHmac1(stringToSign, secret)
|
||||
}
|
||||
|
||||
func (signer *AccessKeySigner) Shutdown() {
|
||||
func (signer *SignerV1) Shutdown() {
|
||||
|
||||
}
|
||||
+4
-4
@@ -19,14 +19,14 @@ import (
|
||||
)
|
||||
|
||||
type SignerV2 struct {
|
||||
credential *credentials.RsaKeyPairCredential
|
||||
credential *credentials.KeyPairCredential
|
||||
}
|
||||
|
||||
func (signer *SignerV2) GetExtraParam() map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewSignerV2(credential *credentials.RsaKeyPairCredential) (*SignerV2, error) {
|
||||
func NewSignerV2(credential *credentials.KeyPairCredential) (*SignerV2, error) {
|
||||
return &SignerV2{
|
||||
credential: credential,
|
||||
}, nil
|
||||
@@ -44,8 +44,8 @@ func (*SignerV2) GetVersion() string {
|
||||
return "1.0"
|
||||
}
|
||||
|
||||
func (signer *SignerV2) GetAccessKeyId() (accessKeyId string, err error) {
|
||||
return signer.credential.PublicKeyId, err
|
||||
func (signer *SignerV2) GetAccessKeyId() string {
|
||||
return signer.credential.PublicKeyId
|
||||
}
|
||||
|
||||
func (signer *SignerV2) Sign(stringToSign, secretSuffix string) string {
|
||||
|
||||
+29
-203
@@ -15,17 +15,13 @@
|
||||
package sdk
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// this value will be replaced while build: -ldflags="-X sdk.version=x.x.x"
|
||||
@@ -40,8 +36,6 @@ type Client struct {
|
||||
|
||||
debug bool
|
||||
isRunning bool
|
||||
// void "panic(write to close channel)" cause of addAsync() after Shutdown()
|
||||
asyncChanLock *sync.RWMutex
|
||||
}
|
||||
|
||||
func (client *Client) Init() (err error) {
|
||||
@@ -50,7 +44,6 @@ func (client *Client) Init() (err error) {
|
||||
|
||||
func (client *Client) InitWithOptions(regionId string, config *Config, credential auth.Credential) (err error) {
|
||||
client.isRunning = true
|
||||
client.asyncChanLock = new(sync.RWMutex)
|
||||
client.regionId = regionId
|
||||
client.config = config
|
||||
if err != nil {
|
||||
@@ -81,10 +74,8 @@ func (client *Client) EnableAsync(routinePoolSize, maxTaskQueueSize int) {
|
||||
go func() {
|
||||
for client.isRunning {
|
||||
select {
|
||||
case task, notClosed := <-client.asyncTaskQueue:
|
||||
if notClosed {
|
||||
task()
|
||||
}
|
||||
case task := <-client.asyncTaskQueue:
|
||||
task()
|
||||
}
|
||||
}
|
||||
}()
|
||||
@@ -100,19 +91,9 @@ func (client *Client) InitWithAccessKey(regionId, accessKeyId, accessKeySecret s
|
||||
return client.InitWithOptions(regionId, config, credential)
|
||||
}
|
||||
|
||||
func (client *Client) InitWithStsToken(regionId, accessKeyId, accessKeySecret, securityToken string) (err error) {
|
||||
func (client *Client) InitWithRoleArn(regionId, accessKeyId, accessKeySecret, roleArn, roleSessionName string) (err error) {
|
||||
config := client.InitClientConfig()
|
||||
credential := &credentials.StsTokenCredential{
|
||||
AccessKeyId: accessKeyId,
|
||||
AccessKeySecret: accessKeySecret,
|
||||
AccessKeyStsToken: securityToken,
|
||||
}
|
||||
return client.InitWithOptions(regionId, config, credential)
|
||||
}
|
||||
|
||||
func (client *Client) InitWithRamRoleArn(regionId, accessKeyId, accessKeySecret, roleArn, roleSessionName string) (err error) {
|
||||
config := client.InitClientConfig()
|
||||
credential := &credentials.RamRoleArnCredential{
|
||||
credential := &credentials.StsAssumeRoleCredential{
|
||||
AccessKeyId: accessKeyId,
|
||||
AccessKeySecret: accessKeySecret,
|
||||
RoleArn: roleArn,
|
||||
@@ -121,9 +102,9 @@ func (client *Client) InitWithRamRoleArn(regionId, accessKeyId, accessKeySecret,
|
||||
return client.InitWithOptions(regionId, config, credential)
|
||||
}
|
||||
|
||||
func (client *Client) InitWithRsaKeyPair(regionId, publicKeyId, privateKey string, sessionExpiration int) (err error) {
|
||||
func (client *Client) InitWithKeyPair(regionId, publicKeyId, privateKey string, sessionExpiration int) (err error) {
|
||||
config := client.InitClientConfig()
|
||||
credential := &credentials.RsaKeyPairCredential{
|
||||
credential := &credentials.KeyPairCredential{
|
||||
PrivateKey: privateKey,
|
||||
PublicKeyId: publicKeyId,
|
||||
SessionExpiration: sessionExpiration,
|
||||
@@ -131,70 +112,27 @@ func (client *Client) InitWithRsaKeyPair(regionId, publicKeyId, privateKey strin
|
||||
return client.InitWithOptions(regionId, config, credential)
|
||||
}
|
||||
|
||||
func (client *Client) InitWithEcsRamRole(regionId, roleName string) (err error) {
|
||||
func (client *Client) InitWithEcsInstance(regionId, roleName string) (err error) {
|
||||
config := client.InitClientConfig()
|
||||
credential := &credentials.EcsRamRoleCredential{
|
||||
credential := &credentials.EcsInstanceCredential{
|
||||
RoleName: roleName,
|
||||
}
|
||||
return client.InitWithOptions(regionId, config, credential)
|
||||
}
|
||||
|
||||
func (client *Client) InitClientConfig() (config *Config) {
|
||||
config = NewConfig()
|
||||
if client.config != nil {
|
||||
return client.config
|
||||
} else {
|
||||
return NewConfig()
|
||||
config = client.config
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (client *Client) DoAction(request requests.AcsRequest, response responses.AcsResponse) (err error) {
|
||||
return client.DoActionWithSigner(request, response, nil)
|
||||
}
|
||||
|
||||
func (client *Client) BuildRequestWithSigner(request requests.AcsRequest, signer auth.Signer) (err error) {
|
||||
// add clientVersion
|
||||
request.GetHeaders()["x-sdk-core-version"] = Version
|
||||
|
||||
regionId := client.regionId
|
||||
if len(request.GetRegionId()) > 0 {
|
||||
regionId = request.GetRegionId()
|
||||
}
|
||||
|
||||
// resolve endpoint
|
||||
resolveParam := &endpoints.ResolveParam{
|
||||
Domain: request.GetDomain(),
|
||||
Product: request.GetProduct(),
|
||||
RegionId: regionId,
|
||||
LocationProduct: request.GetLocationServiceCode(),
|
||||
LocationEndpointType: request.GetLocationEndpointType(),
|
||||
CommonApi: client.ProcessCommonRequest,
|
||||
}
|
||||
endpoint, err := endpoints.Resolve(resolveParam)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
request.SetDomain(endpoint)
|
||||
|
||||
// init request params
|
||||
err = requests.InitParams(request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// signature
|
||||
var finalSigner auth.Signer
|
||||
if signer != nil {
|
||||
finalSigner = signer
|
||||
} else {
|
||||
finalSigner = client.signer
|
||||
}
|
||||
httpRequest, err := buildHttpRequest(request, finalSigner, regionId)
|
||||
if client.config.UserAgent != "" {
|
||||
httpRequest.Header.Set("User-Agent", client.config.UserAgent)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (client *Client) DoActionWithSigner(request requests.AcsRequest, response responses.AcsResponse, signer auth.Signer) (err error) {
|
||||
|
||||
// add clientVersion
|
||||
@@ -207,12 +145,12 @@ func (client *Client) DoActionWithSigner(request requests.AcsRequest, response r
|
||||
|
||||
// resolve endpoint
|
||||
resolveParam := &endpoints.ResolveParam{
|
||||
Domain: request.GetDomain(),
|
||||
Product: request.GetProduct(),
|
||||
RegionId: regionId,
|
||||
LocationProduct: request.GetLocationServiceCode(),
|
||||
LocationEndpointType: request.GetLocationEndpointType(),
|
||||
CommonApi: client.ProcessCommonRequest,
|
||||
Domain: request.GetDomain(),
|
||||
Product: request.GetProduct(),
|
||||
RegionId: client.regionId,
|
||||
LocationProduct: request.GetLocationServiceCode(),
|
||||
LocationEndpoint: request.GetLocationEndpointType(),
|
||||
CommonApi: client.ProcessCommonRequest,
|
||||
}
|
||||
endpoint, err := endpoints.Resolve(resolveParam)
|
||||
if err != nil {
|
||||
@@ -220,9 +158,6 @@ func (client *Client) DoActionWithSigner(request requests.AcsRequest, response r
|
||||
}
|
||||
request.SetDomain(endpoint)
|
||||
|
||||
if request.GetScheme() == "" {
|
||||
request.SetScheme(client.config.Scheme)
|
||||
}
|
||||
// init request params
|
||||
err = requests.InitParams(request)
|
||||
if err != nil {
|
||||
@@ -230,115 +165,43 @@ func (client *Client) DoActionWithSigner(request requests.AcsRequest, response r
|
||||
}
|
||||
|
||||
// signature
|
||||
var finalSigner auth.Signer
|
||||
if signer != nil {
|
||||
finalSigner = signer
|
||||
err = auth.Sign(request, signer, regionId)
|
||||
} else {
|
||||
finalSigner = client.signer
|
||||
}
|
||||
httpRequest, err := buildHttpRequest(request, finalSigner, regionId)
|
||||
if client.config.UserAgent != "" {
|
||||
httpRequest.Header.Set("User-Agent", client.config.UserAgent)
|
||||
err = auth.Sign(request, client.signer, regionId)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var httpResponse *http.Response
|
||||
for retryTimes := 0; retryTimes <= client.config.MaxRetryTime; retryTimes++ {
|
||||
httpResponse, err = client.httpClient.Do(httpRequest)
|
||||
|
||||
var timeout bool
|
||||
// receive error
|
||||
if err != nil {
|
||||
if !client.config.AutoRetry {
|
||||
return
|
||||
} else if timeout = isTimeout(err); !timeout {
|
||||
// if not timeout error, return
|
||||
return
|
||||
} else if retryTimes >= client.config.MaxRetryTime {
|
||||
// timeout but reached the max retry times, return
|
||||
timeoutErrorMsg := fmt.Sprintf(errors.TimeoutErrorMessage, strconv.Itoa(retryTimes+1), strconv.Itoa(retryTimes+1))
|
||||
err = errors.NewClientError(errors.TimeoutErrorCode, timeoutErrorMsg, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
// if status code >= 500 or timeout, will trigger retry
|
||||
if client.config.AutoRetry && (timeout || isServerError(httpResponse)) {
|
||||
// rewrite signatureNonce and signature
|
||||
httpRequest, err = buildHttpRequest(request, finalSigner, regionId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
err = responses.Unmarshal(response, httpResponse, request.GetAcceptFormat())
|
||||
// wrap server errors
|
||||
if serverErr, ok := err.(*errors.ServerError); ok {
|
||||
var wrapInfo = map[string]string{}
|
||||
wrapInfo["StringToSign"] = request.GetStringToSign()
|
||||
err = errors.WrapServerError(serverErr, wrapInfo)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func buildHttpRequest(request requests.AcsRequest, singer auth.Signer, regionId string) (httpRequest *http.Request, err error) {
|
||||
err = auth.Sign(request, singer, regionId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
requestMethod := request.GetMethod()
|
||||
requestUrl := request.BuildUrl()
|
||||
requestUrl := request.GetUrl()
|
||||
body := request.GetBodyReader()
|
||||
httpRequest, err = http.NewRequest(requestMethod, requestUrl, body)
|
||||
httpRequest, err := http.NewRequest(requestMethod, requestUrl, body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for key, value := range request.GetHeaders() {
|
||||
httpRequest.Header[key] = []string{value}
|
||||
}
|
||||
// host is a special case
|
||||
if host, containsHost := request.GetHeaders()["Host"]; containsHost {
|
||||
httpRequest.Host = host
|
||||
httpResponse, err := client.httpClient.Do(httpRequest)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = responses.Unmarshal(response, httpResponse, request.GetAcceptFormat())
|
||||
return
|
||||
}
|
||||
|
||||
func isTimeout(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
netErr, isNetError := err.(net.Error)
|
||||
return isNetError && netErr.Timeout()
|
||||
}
|
||||
|
||||
func isServerError(httpResponse *http.Response) bool {
|
||||
return httpResponse.StatusCode >= http.StatusInternalServerError
|
||||
}
|
||||
|
||||
/**
|
||||
only block when any one of the following occurs:
|
||||
1. the asyncTaskQueue is full, increase the queue size to avoid this
|
||||
2. Shutdown() in progressing, the client is being closed
|
||||
**/
|
||||
func (client *Client) AddAsyncTask(task func()) (err error) {
|
||||
if client.asyncTaskQueue != nil {
|
||||
client.asyncChanLock.RLock()
|
||||
defer client.asyncChanLock.RUnlock()
|
||||
if client.isRunning {
|
||||
client.asyncTaskQueue <- task
|
||||
}
|
||||
client.asyncTaskQueue <- task
|
||||
} else {
|
||||
err = errors.NewClientError(errors.AsyncFunctionNotEnabledCode, errors.AsyncFunctionNotEnabledMessage, nil)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (client *Client) GetConfig() *Config {
|
||||
return client.config
|
||||
}
|
||||
|
||||
func NewClient() (client *Client, err error) {
|
||||
client = &Client{}
|
||||
err = client.Init()
|
||||
@@ -357,40 +220,6 @@ func NewClientWithAccessKey(regionId, accessKeyId, accessKeySecret string) (clie
|
||||
return
|
||||
}
|
||||
|
||||
func NewClientWithStsToken(regionId, stsAccessKeyId, stsAccessKeySecret, stsToken string) (client *Client, err error) {
|
||||
client = &Client{}
|
||||
err = client.InitWithStsToken(regionId, stsAccessKeyId, stsAccessKeySecret, stsToken)
|
||||
return
|
||||
}
|
||||
|
||||
func NewClientWithRamRoleArn(regionId string, accessKeyId, accessKeySecret, roleArn, roleSessionName string) (client *Client, err error) {
|
||||
client = &Client{}
|
||||
err = client.InitWithRamRoleArn(regionId, accessKeyId, accessKeySecret, roleArn, roleSessionName)
|
||||
return
|
||||
}
|
||||
|
||||
func NewClientWithEcsRamRole(regionId string, roleName string) (client *Client, err error) {
|
||||
client = &Client{}
|
||||
err = client.InitWithEcsRamRole(regionId, roleName)
|
||||
return
|
||||
}
|
||||
|
||||
func NewClientWithRsaKeyPair(regionId string, publicKeyId, privateKey string, sessionExpiration int) (client *Client, err error) {
|
||||
client = &Client{}
|
||||
err = client.InitWithRsaKeyPair(regionId, publicKeyId, privateKey, sessionExpiration)
|
||||
return
|
||||
}
|
||||
|
||||
// Deprecated: Use NewClientWithRamRoleArn in this package instead.
|
||||
func NewClientWithStsRoleArn(regionId string, accessKeyId, accessKeySecret, roleArn, roleSessionName string) (client *Client, err error) {
|
||||
return NewClientWithRamRoleArn(regionId, accessKeyId, accessKeySecret, roleArn, roleSessionName)
|
||||
}
|
||||
|
||||
// Deprecated: Use NewClientWithEcsRamRole in this package instead.
|
||||
func NewClientWithStsRoleNameOnEcs(regionId string, roleName string) (client *Client, err error) {
|
||||
return NewClientWithEcsRamRole(regionId, roleName)
|
||||
}
|
||||
|
||||
func (client *Client) ProcessCommonRequest(request *requests.CommonRequest) (response *responses.CommonResponse, err error) {
|
||||
request.TransToAcsRequest()
|
||||
response = responses.NewCommonResponse()
|
||||
@@ -411,9 +240,6 @@ func (client *Client) ProcessCommonRequestWithSigner(request *requests.CommonReq
|
||||
|
||||
func (client *Client) Shutdown() {
|
||||
client.signer.Shutdown()
|
||||
// lock the addAsync()
|
||||
client.asyncChanLock.Lock()
|
||||
defer client.asyncChanLock.Unlock()
|
||||
client.isRunning = false
|
||||
close(client.asyncTaskQueue)
|
||||
client.isRunning = false
|
||||
}
|
||||
|
||||
+1
-37
@@ -25,12 +25,11 @@ type Config struct {
|
||||
MaxRetryTime int `default:"3"`
|
||||
UserAgent string `default:""`
|
||||
Debug bool `default:"false"`
|
||||
Timeout time.Duration `default:"10000000000"`
|
||||
Timeout time.Duration `default:""`
|
||||
HttpTransport *http.Transport `default:""`
|
||||
EnableAsync bool `default:"false"`
|
||||
MaxTaskQueueSize int `default:"1000"`
|
||||
GoRoutinePoolSize int `default:"5"`
|
||||
Scheme string `default:"HTTP"`
|
||||
}
|
||||
|
||||
func NewConfig() (config *Config) {
|
||||
@@ -44,41 +43,6 @@ func (c *Config) WithTimeout(timeout time.Duration) *Config {
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Config) WithAutoRetry(isAutoRetry bool) *Config {
|
||||
c.AutoRetry = isAutoRetry
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Config) WithMaxRetryTime(maxRetryTime int) *Config {
|
||||
c.MaxRetryTime = maxRetryTime
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Config) WithUserAgent(userAgent string) *Config {
|
||||
c.UserAgent = userAgent
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Config) WithHttpTransport(httpTransport *http.Transport) *Config {
|
||||
c.HttpTransport = httpTransport
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Config) WithEnableAsync(isEnableAsync bool) *Config {
|
||||
c.EnableAsync = isEnableAsync
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Config) WithMaxTaskQueueSize(maxTaskQueueSize int) *Config {
|
||||
c.MaxTaskQueueSize = maxTaskQueueSize
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Config) WithGoRoutinePoolSize(goRoutinePoolSize int) *Config {
|
||||
c.GoRoutinePoolSize = goRoutinePoolSize
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Config) WithDebug(isDebug bool) *Config {
|
||||
c.Debug = isDebug
|
||||
return c
|
||||
|
||||
+4778
File diff suppressed because it is too large
Load Diff
-505
@@ -1,505 +0,0 @@
|
||||
package endpoints
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const endpointsJson = "{" +
|
||||
" \"products\":[" +
|
||||
" {" +
|
||||
" \"code\": \"aegis\"," +
|
||||
" \"document_id\": \"28449\"," +
|
||||
" \"location_service_code\": \"vipaegis\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"aegis.cn-hangzhou.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"alidns\"," +
|
||||
" \"document_id\": \"29739\"," +
|
||||
" \"location_service_code\": \"alidns\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"alidns.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"arms\"," +
|
||||
" \"document_id\": \"42924\"," +
|
||||
" \"location_service_code\": \"\"," +
|
||||
" \"regional_endpoints\": [ {" +
|
||||
" \"region\": \"ap-southeast-1\"," +
|
||||
" \"endpoint\": \"arms.ap-southeast-1.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"cn-beijing\"," +
|
||||
" \"endpoint\": \"arms.cn-beijing.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"cn-hangzhou\"," +
|
||||
" \"endpoint\": \"arms.cn-hangzhou.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"cn-hongkong\"," +
|
||||
" \"endpoint\": \"arms.cn-hongkong.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"cn-qingdao\"," +
|
||||
" \"endpoint\": \"arms.cn-qingdao.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"cn-shanghai\"," +
|
||||
" \"endpoint\": \"arms.cn-shanghai.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"cn-shenzhen\"," +
|
||||
" \"endpoint\": \"arms.cn-shenzhen.aliyuncs.com\"" +
|
||||
" }]," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"arms.[RegionId].aliyuncs.com\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"batchcompute\"," +
|
||||
" \"document_id\": \"44717\"," +
|
||||
" \"location_service_code\": \"\"," +
|
||||
" \"regional_endpoints\": [ {" +
|
||||
" \"region\": \"ap-southeast-1\"," +
|
||||
" \"endpoint\": \"batchcompute.ap-southeast-1.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"cn-beijing\"," +
|
||||
" \"endpoint\": \"batchcompute.cn-beijing.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"cn-hangzhou\"," +
|
||||
" \"endpoint\": \"batchcompute.cn-hangzhou.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"cn-huhehaote\"," +
|
||||
" \"endpoint\": \"batchcompute.cn-huhehaote.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"cn-qingdao\"," +
|
||||
" \"endpoint\": \"batchcompute.cn-qingdao.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"cn-shanghai\"," +
|
||||
" \"endpoint\": \"batchcompute.cn-shanghai.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"cn-shenzhen\"," +
|
||||
" \"endpoint\": \"batchcompute.cn-shenzhen.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"cn-zhangjiakou\"," +
|
||||
" \"endpoint\": \"batchcompute.cn-zhangjiakou.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"us-west-1\"," +
|
||||
" \"endpoint\": \"batchcompute.us-west-1.aliyuncs.com\"" +
|
||||
" }]," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"batchcompute.[RegionId].aliyuncs.com\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"ccc\"," +
|
||||
" \"document_id\": \"63027\"," +
|
||||
" \"location_service_code\": \"ccc\"," +
|
||||
" \"regional_endpoints\": [ {" +
|
||||
" \"region\": \"cn-hangzhou\"," +
|
||||
" \"endpoint\": \"ccc.cn-hangzhou.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"cn-shanghai\"," +
|
||||
" \"endpoint\": \"ccc.cn-shanghai.aliyuncs.com\"" +
|
||||
" }]," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"ccc.[RegionId].aliyuncs.com\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"cdn\"," +
|
||||
" \"document_id\": \"27148\"," +
|
||||
" \"location_service_code\": \"\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"cdn.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"cds\"," +
|
||||
" \"document_id\": \"62887\"," +
|
||||
" \"location_service_code\": \"\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"cds.cn-beijing.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"chatbot\"," +
|
||||
" \"document_id\": \"60760\"," +
|
||||
" \"location_service_code\": \"beebot\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"chatbot.[RegionId].aliyuncs.com\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"cloudapi\"," +
|
||||
" \"document_id\": \"43590\"," +
|
||||
" \"location_service_code\": \"apigateway\"," +
|
||||
" \"regional_endpoints\": [ {" +
|
||||
" \"region\": \"ap-northeast-1\"," +
|
||||
" \"endpoint\": \"apigateway.ap-northeast-1.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"us-west-1\"," +
|
||||
" \"endpoint\": \"apigateway.us-west-1.aliyuncs.com\"" +
|
||||
" }]," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"apigateway.[RegionId].aliyuncs.com\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"cloudauth\"," +
|
||||
" \"document_id\": \"60687\"," +
|
||||
" \"location_service_code\": \"cloudauth\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"cloudauth.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"cloudphoto\"," +
|
||||
" \"document_id\": \"59902\"," +
|
||||
" \"location_service_code\": \"cloudphoto\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"cloudphoto.[RegionId].aliyuncs.com\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"cloudwf\"," +
|
||||
" \"document_id\": \"58111\"," +
|
||||
" \"location_service_code\": \"\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"cloudwf.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"cms\"," +
|
||||
" \"document_id\": \"28615\"," +
|
||||
" \"location_service_code\": \"cms\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"cr\"," +
|
||||
" \"document_id\": \"60716\"," +
|
||||
" \"location_service_code\": \"\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"cr.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"cs\"," +
|
||||
" \"document_id\": \"26043\"," +
|
||||
" \"location_service_code\": \"\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"cs.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"csb\"," +
|
||||
" \"document_id\": \"64837\"," +
|
||||
" \"location_service_code\": \"\"," +
|
||||
" \"regional_endpoints\": [ {" +
|
||||
" \"region\": \"cn-beijing\"," +
|
||||
" \"endpoint\": \"csb.cn-beijing.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"cn-hangzhou\"," +
|
||||
" \"endpoint\": \"csb.cn-hangzhou.aliyuncs.com\"" +
|
||||
" }]," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"csb.[RegionId].aliyuncs.com\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"dds\"," +
|
||||
" \"document_id\": \"61715\"," +
|
||||
" \"location_service_code\": \"dds\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"mongodb.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"mongodb.[RegionId].aliyuncs.com\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"dm\"," +
|
||||
" \"document_id\": \"29434\"," +
|
||||
" \"location_service_code\": \"\"," +
|
||||
" \"regional_endpoints\": [ {" +
|
||||
" \"region\": \"ap-southeast-1\"," +
|
||||
" \"endpoint\": \"dm.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"ap-southeast-2\"," +
|
||||
" \"endpoint\": \"dm.ap-southeast-2.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"cn-beijing\"," +
|
||||
" \"endpoint\": \"dm.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"cn-hangzhou\"," +
|
||||
" \"endpoint\": \"dm.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"cn-hongkong\"," +
|
||||
" \"endpoint\": \"dm.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"cn-qingdao\"," +
|
||||
" \"endpoint\": \"dm.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"cn-shanghai\"," +
|
||||
" \"endpoint\": \"dm.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"cn-shenzhen\"," +
|
||||
" \"endpoint\": \"dm.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"us-east-1\"," +
|
||||
" \"endpoint\": \"dm.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"us-west-1\"," +
|
||||
" \"endpoint\": \"dm.aliyuncs.com\"" +
|
||||
" }]," +
|
||||
" \"global_endpoint\": \"dm.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"dm.[RegionId].aliyuncs.com\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"domain\"," +
|
||||
" \"document_id\": \"42875\"," +
|
||||
" \"location_service_code\": \"\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"domain.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"domain.aliyuncs.com\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"domain-intl\"," +
|
||||
" \"document_id\": \"\"," +
|
||||
" \"location_service_code\": \"\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"domain-intl.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"domain-intl.aliyuncs.com\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"drds\"," +
|
||||
" \"document_id\": \"51111\"," +
|
||||
" \"location_service_code\": \"\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"drds.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"drds.aliyuncs.com\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"ecs\"," +
|
||||
" \"document_id\": \"25484\"," +
|
||||
" \"location_service_code\": \"ecs\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"emr\"," +
|
||||
" \"document_id\": \"28140\"," +
|
||||
" \"location_service_code\": \"emr\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"emr.[RegionId].aliyuncs.com\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"ess\"," +
|
||||
" \"document_id\": \"25925\"," +
|
||||
" \"location_service_code\": \"ess\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"ess.[RegionId].aliyuncs.com\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"green\"," +
|
||||
" \"document_id\": \"28427\"," +
|
||||
" \"location_service_code\": \"green\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"green.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"hpc\"," +
|
||||
" \"document_id\": \"35201\"," +
|
||||
" \"location_service_code\": \"hpc\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"hpc.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"httpdns\"," +
|
||||
" \"document_id\": \"52679\"," +
|
||||
" \"location_service_code\": \"\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"httpdns-api.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"iot\"," +
|
||||
" \"document_id\": \"30557\"," +
|
||||
" \"location_service_code\": \"iot\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"iot.[RegionId].aliyuncs.com\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"itaas\"," +
|
||||
" \"document_id\": \"55759\"," +
|
||||
" \"location_service_code\": \"\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"itaas.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"jaq\"," +
|
||||
" \"document_id\": \"35037\"," +
|
||||
" \"location_service_code\": \"\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"jaq.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"live\"," +
|
||||
" \"document_id\": \"48207\"," +
|
||||
" \"location_service_code\": \"live\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"live.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"mts\"," +
|
||||
" \"document_id\": \"29212\"," +
|
||||
" \"location_service_code\": \"mts\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"nas\"," +
|
||||
" \"document_id\": \"62598\"," +
|
||||
" \"location_service_code\": \"nas\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"ons\"," +
|
||||
" \"document_id\": \"44416\"," +
|
||||
" \"location_service_code\": \"ons\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"polardb\"," +
|
||||
" \"document_id\": \"58764\"," +
|
||||
" \"location_service_code\": \"polardb\"," +
|
||||
" \"regional_endpoints\": [ {" +
|
||||
" \"region\": \"ap-south-1\"," +
|
||||
" \"endpoint\": \"polardb.ap-south-1.aliyuncs.com\"" +
|
||||
" }, {" +
|
||||
" \"region\": \"ap-southeast-5\"," +
|
||||
" \"endpoint\": \"polardb.ap-southeast-5.aliyuncs.com\"" +
|
||||
" }]," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"polardb.aliyuncs.com\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"push\"," +
|
||||
" \"document_id\": \"30074\"," +
|
||||
" \"location_service_code\": \"\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"cloudpush.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"qualitycheck\"," +
|
||||
" \"document_id\": \"50807\"," +
|
||||
" \"location_service_code\": \"\"," +
|
||||
" \"regional_endpoints\": [ {" +
|
||||
" \"region\": \"cn-hangzhou\"," +
|
||||
" \"endpoint\": \"qualitycheck.cn-hangzhou.aliyuncs.com\"" +
|
||||
" }]," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"r-kvstore\"," +
|
||||
" \"document_id\": \"60831\"," +
|
||||
" \"location_service_code\": \"redisa\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"ram\"," +
|
||||
" \"document_id\": \"28672\"," +
|
||||
" \"location_service_code\": \"\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"ram.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"rds\"," +
|
||||
" \"document_id\": \"26223\"," +
|
||||
" \"location_service_code\": \"rds\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"ros\"," +
|
||||
" \"document_id\": \"28899\"," +
|
||||
" \"location_service_code\": \"\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"ros.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"sas-api\"," +
|
||||
" \"document_id\": \"28498\"," +
|
||||
" \"location_service_code\": \"sas\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"slb\"," +
|
||||
" \"document_id\": \"27565\"," +
|
||||
" \"location_service_code\": \"slb\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"sts\"," +
|
||||
" \"document_id\": \"28756\"," +
|
||||
" \"location_service_code\": \"\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"sts.aliyuncs.com\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"vod\"," +
|
||||
" \"document_id\": \"60574\"," +
|
||||
" \"location_service_code\": \"vod\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"vpc\"," +
|
||||
" \"document_id\": \"34962\"," +
|
||||
" \"location_service_code\": \"vpc\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }," +
|
||||
" {" +
|
||||
" \"code\": \"waf\"," +
|
||||
" \"document_id\": \"62847\"," +
|
||||
" \"location_service_code\": \"waf\"," +
|
||||
" \"regional_endpoints\": []," +
|
||||
" \"global_endpoint\": \"\"," +
|
||||
" \"regional_endpoint_pattern\": \"\"" +
|
||||
" }]" +
|
||||
"}"
|
||||
|
||||
var initOnce sync.Once
|
||||
var data interface{}
|
||||
|
||||
func getEndpointConfigData() interface{} {
|
||||
initOnce.Do(func() {
|
||||
err := json.Unmarshal([]byte(endpointsJson), &data)
|
||||
if err != nil {
|
||||
fmt.Println("init endpoint config data failed.", err)
|
||||
}
|
||||
})
|
||||
return data
|
||||
}
|
||||
Generated
Vendored
-37
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* 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 endpoints
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/jmespath/go-jmespath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type LocalGlobalResolver struct {
|
||||
}
|
||||
|
||||
func (resolver *LocalGlobalResolver) TryResolve(param *ResolveParam) (endpoint string, support bool, err error) {
|
||||
// get the global endpoints configs
|
||||
endpointExpression := fmt.Sprintf("products[?code=='%s'].global_endpoint", strings.ToLower(param.Product))
|
||||
endpointData, err := jmespath.Search(endpointExpression, getEndpointConfigData())
|
||||
if err == nil && endpointData != nil && len(endpointData.([]interface{})) > 0 {
|
||||
endpoint = endpointData.([]interface{})[0].(string)
|
||||
support = len(endpoint) > 0
|
||||
return endpoint, support, nil
|
||||
}
|
||||
support = false
|
||||
return
|
||||
}
|
||||
Generated
Vendored
-41
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* 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 endpoints
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/jmespath/go-jmespath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type LocalRegionalResolver struct {
|
||||
}
|
||||
|
||||
func (resolver *LocalRegionalResolver) TryResolve(param *ResolveParam) (endpoint string, support bool, err error) {
|
||||
// get the regional endpoints configs
|
||||
regionalExpression := fmt.Sprintf("products[?code=='%s'].regional_endpoints", strings.ToLower(param.Product))
|
||||
regionalData, err := jmespath.Search(regionalExpression, getEndpointConfigData())
|
||||
if err == nil && regionalData != nil && len(regionalData.([]interface{})) > 0 {
|
||||
endpointExpression := fmt.Sprintf("[0][?region=='%s'].endpoint", strings.ToLower(param.RegionId))
|
||||
endpointData, err := jmespath.Search(endpointExpression, regionalData)
|
||||
if err == nil && endpointData != nil && len(endpointData.([]interface{})) > 0 {
|
||||
endpoint = endpointData.([]interface{})[0].(string)
|
||||
support = len(endpoint) > 0
|
||||
return endpoint, support, nil
|
||||
}
|
||||
}
|
||||
support = false
|
||||
return
|
||||
}
|
||||
Generated
Vendored
+110
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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 endpoints
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var readXmlOnce sync.Once
|
||||
var v = Endpoints{}
|
||||
|
||||
type LocalXmlResolver struct {
|
||||
}
|
||||
|
||||
func (resolver *LocalXmlResolver) TryResolve(param *ResolveParam) (endpoint string, support bool, err error) {
|
||||
readXmlOnce.Do(func() {
|
||||
_, file, _, _ := runtime.Caller(0)
|
||||
filename := filepath.Join(file, "../endpoints.xml")
|
||||
|
||||
data, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
support = false
|
||||
return
|
||||
}
|
||||
|
||||
err = xml.Unmarshal(data, &v)
|
||||
if err != nil {
|
||||
support = false
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
for _, xmlEndpoint := range v.EndpointList {
|
||||
for _, xmlRegionId := range xmlEndpoint.RegionIds.Id {
|
||||
if xmlRegionId == param.RegionId {
|
||||
for _, xmlProduct := range xmlEndpoint.Products.ProductList {
|
||||
if xmlProduct.ProductName == param.Product {
|
||||
endpoint = xmlProduct.DomainName
|
||||
support = true
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
support = false
|
||||
return
|
||||
}
|
||||
|
||||
func GetCurrentPath() string {
|
||||
s, err := exec.LookPath(os.Args[0])
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
s = strings.Replace(s, "\\", "/", -1)
|
||||
s = strings.Replace(s, "\\\\", "/", -1)
|
||||
i := strings.LastIndex(s, "/")
|
||||
path := string(s[0 : i+1])
|
||||
return path
|
||||
}
|
||||
|
||||
type Endpoints struct {
|
||||
XMLName xml.Name `xml:"Endpoints"`
|
||||
EndpointList []Endpoint `xml:"Endpoint"`
|
||||
}
|
||||
|
||||
type Endpoint struct {
|
||||
XMLName xml.Name `xml:"Endpoint"`
|
||||
Name string `xml:"name,attr"`
|
||||
RegionIds RegionIds `xml:"RegionIds"`
|
||||
Products Products `xml:"Products"`
|
||||
}
|
||||
|
||||
type RegionIds struct {
|
||||
Id []string `xml:"RegionId"`
|
||||
}
|
||||
|
||||
type Products struct {
|
||||
ProductList []Product `xml:"Product"`
|
||||
}
|
||||
|
||||
type RegionId struct {
|
||||
XMLName string `xml:"RegionId"`
|
||||
}
|
||||
|
||||
type Product struct {
|
||||
ProductName string `xml:"ProductName"`
|
||||
DomainName string `xml:"DomainName"`
|
||||
}
|
||||
+11
-26
@@ -16,7 +16,6 @@ package endpoints
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -24,15 +23,8 @@ const (
|
||||
EndpointCacheExpireTime = 3600 //Seconds
|
||||
)
|
||||
|
||||
var lastClearTimePerProduct = struct {
|
||||
sync.RWMutex
|
||||
cache map[string]int64
|
||||
}{cache: make(map[string]int64)}
|
||||
|
||||
var endpointCache = struct {
|
||||
sync.RWMutex
|
||||
cache map[string]string
|
||||
}{cache: make(map[string]string)}
|
||||
var lastClearTimePerProduct map[string]int64 = make(map[string]int64)
|
||||
var endpointCache map[string]string = make(map[string]string)
|
||||
|
||||
type LocationResolver struct {
|
||||
}
|
||||
@@ -45,31 +37,30 @@ func (resolver *LocationResolver) TryResolve(param *ResolveParam) (endpoint stri
|
||||
|
||||
//get from cache
|
||||
cacheKey := param.Product + "#" + param.RegionId
|
||||
if endpointCache.cache != nil && len(endpointCache.cache[cacheKey]) > 0 && !CheckCacheIsExpire(cacheKey) {
|
||||
endpoint = endpointCache.cache[cacheKey]
|
||||
if endpointCache != nil && len(endpointCache[cacheKey]) > 0 && !CheckCacheIsExpire(cacheKey) {
|
||||
endpoint = endpointCache[cacheKey]
|
||||
support = true
|
||||
return
|
||||
}
|
||||
|
||||
//get from remote
|
||||
getEndpointRequest := requests.NewCommonRequest()
|
||||
|
||||
getEndpointRequest.Product = "Location"
|
||||
getEndpointRequest.Version = "2015-06-12"
|
||||
getEndpointRequest.ApiName = "DescribeEndpoints"
|
||||
getEndpointRequest.Domain = "location.aliyuncs.com"
|
||||
getEndpointRequest.Method = "GET"
|
||||
getEndpointRequest.Scheme = requests.HTTPS
|
||||
|
||||
getEndpointRequest.QueryParams["Id"] = param.RegionId
|
||||
getEndpointRequest.QueryParams["ServiceCode"] = param.LocationProduct
|
||||
if len(param.LocationEndpointType) > 0 {
|
||||
getEndpointRequest.QueryParams["Type"] = param.LocationEndpointType
|
||||
if len(param.LocationEndpoint) > 0 {
|
||||
getEndpointRequest.QueryParams["Type"] = param.LocationEndpoint
|
||||
} else {
|
||||
getEndpointRequest.QueryParams["Type"] = "openAPI"
|
||||
}
|
||||
|
||||
response, err := param.CommonApi(getEndpointRequest)
|
||||
//{"Endpoints":{"Endpoint":[{"Protocols":{"Protocols":["HTTP","HTTPS"]},"Type":"openAPI","Namespace":"26842","Id":"cn-hangzhou","SerivceCode":"apigateway","Endpoint":"apigateway.cn-hangzhou.aliyuncs.com"}]},"RequestId":"3287538B-19A0-4550-9995-143C5EDBD955","Success":true}
|
||||
var getEndpointResponse GetEndpointResponse
|
||||
if !response.IsSuccess() {
|
||||
support = false
|
||||
@@ -87,12 +78,8 @@ func (resolver *LocationResolver) TryResolve(param *ResolveParam) (endpoint stri
|
||||
}
|
||||
if len(getEndpointResponse.Endpoints.Endpoint[0].Endpoint) > 0 {
|
||||
endpoint = getEndpointResponse.Endpoints.Endpoint[0].Endpoint
|
||||
endpointCache.Lock()
|
||||
endpointCache.cache[cacheKey] = endpoint
|
||||
endpointCache.Unlock()
|
||||
lastClearTimePerProduct.Lock()
|
||||
lastClearTimePerProduct.cache[cacheKey] = time.Now().Unix()
|
||||
lastClearTimePerProduct.Unlock()
|
||||
endpointCache[cacheKey] = endpoint
|
||||
lastClearTimePerProduct[cacheKey] = time.Now().Unix()
|
||||
support = true
|
||||
return
|
||||
}
|
||||
@@ -102,12 +89,10 @@ func (resolver *LocationResolver) TryResolve(param *ResolveParam) (endpoint stri
|
||||
}
|
||||
|
||||
func CheckCacheIsExpire(cacheKey string) bool {
|
||||
lastClearTime := lastClearTimePerProduct.cache[cacheKey]
|
||||
lastClearTime := lastClearTimePerProduct[cacheKey]
|
||||
if lastClearTime <= 0 {
|
||||
lastClearTime = time.Now().Unix()
|
||||
lastClearTimePerProduct.Lock()
|
||||
lastClearTimePerProduct.cache[cacheKey] = lastClearTime
|
||||
lastClearTimePerProduct.Unlock()
|
||||
lastClearTimePerProduct[cacheKey] = lastClearTime
|
||||
}
|
||||
|
||||
now := time.Now().Unix()
|
||||
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* 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 endpoints
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const keyFormatter = "%s::%s"
|
||||
|
||||
var endpointMapping = make(map[string]string)
|
||||
|
||||
func AddEndpointMapping(regionId, productId, endpoint string) (err error) {
|
||||
key := fmt.Sprintf(keyFormatter, strings.ToLower(regionId), strings.ToLower(productId))
|
||||
endpointMapping[key] = endpoint
|
||||
return nil
|
||||
}
|
||||
|
||||
type MappingResolver struct {
|
||||
}
|
||||
|
||||
func (resolver *MappingResolver) TryResolve(param *ResolveParam) (endpoint string, support bool, err error) {
|
||||
key := fmt.Sprintf(keyFormatter, strings.ToLower(param.RegionId), strings.ToLower(param.Product))
|
||||
endpoint, contains := endpointMapping[key]
|
||||
return endpoint, contains, nil
|
||||
}
|
||||
+9
-11
@@ -44,8 +44,8 @@ func Resolve(param *ResolveParam) (endpoint string, err error) {
|
||||
}
|
||||
|
||||
// not support
|
||||
errorMsg := fmt.Sprintf(errors.CanNotResolveEndpointErrorMessage, param, ResolveEndpointUserGuideLink)
|
||||
err = errors.NewClientError(errors.CanNotResolveEndpointErrorCode, errorMsg, nil)
|
||||
errorMsg := fmt.Sprintf(errors.CanNotResolveEndpointMessage, param, ResolveEndpointUserGuideLink)
|
||||
err = errors.NewClientError(errors.CanNotResolveEndpointCode, errorMsg, nil)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -53,22 +53,20 @@ func getAllResolvers() []Resolver {
|
||||
once.Do(func() {
|
||||
resolvers = []Resolver{
|
||||
&SimpleHostResolver{},
|
||||
&MappingResolver{},
|
||||
&LocationResolver{},
|
||||
&LocalRegionalResolver{},
|
||||
&LocalGlobalResolver{},
|
||||
&LocalXmlResolver{},
|
||||
}
|
||||
})
|
||||
return resolvers
|
||||
}
|
||||
|
||||
type ResolveParam struct {
|
||||
Domain string
|
||||
Product string
|
||||
RegionId string
|
||||
LocationProduct string
|
||||
LocationEndpointType string
|
||||
CommonApi func(request *requests.CommonRequest) (response *responses.CommonResponse, err error) `json:"-"`
|
||||
Domain string
|
||||
Product string
|
||||
RegionId string
|
||||
LocationProduct string
|
||||
LocationEndpoint string
|
||||
CommonApi func(request *requests.CommonRequest) (response *responses.CommonResponse, err error) `json:"-"`
|
||||
}
|
||||
|
||||
func (param *ResolveParam) String() string {
|
||||
|
||||
+13
-25
@@ -14,35 +14,27 @@
|
||||
|
||||
package errors
|
||||
|
||||
import "fmt"
|
||||
|
||||
const (
|
||||
DefaultClientErrorStatus = 400
|
||||
DefaultClientErrorCode = "SDK.ClientError"
|
||||
|
||||
UnsupportedCredentialErrorCode = "SDK.UnsupportedCredential"
|
||||
UnsupportedCredentialErrorMessage = "Specified credential (type = %s) is not supported, please check"
|
||||
UnsupportedCredentialCode = "SDK.UnsupportedCredential"
|
||||
UnsupportedCredentialMessage = "Specified credential (type = %s) is not supported, please check"
|
||||
|
||||
CanNotResolveEndpointErrorCode = "SDK.CanNotResolveEndpoint"
|
||||
CanNotResolveEndpointErrorMessage = "Can not resolve endpoint(param = %s), please check your accessKey with secret, and read the user guide\n %s"
|
||||
CanNotResolveEndpointCode = "SDK.CanNotResolveEndpoint"
|
||||
CanNotResolveEndpointMessage = "Can not resolve endpoint(param = %s), please check the user guide\n %s"
|
||||
|
||||
UnsupportedParamPositionErrorCode = "SDK.UnsupportedParamPosition"
|
||||
UnsupportedParamPositionErrorMessage = "Specified param position (%s) is not supported, please upgrade sdk and retry"
|
||||
UnsupportedParamPositionCode = "SDK.UnsupportedParamPosition"
|
||||
UnsupportedParamPositionMessage = "Specified param position (%s) is not supported, please upgrade sdk and retry"
|
||||
|
||||
AsyncFunctionNotEnabledCode = "SDK.AsyncFunctionNotEnabled"
|
||||
AsyncFunctionNotEnabledMessage = "Async function is not enabled in client, please invoke 'client.EnableAsync' function"
|
||||
|
||||
UnknownRequestTypeErrorCode = "SDK.UnknownRequestType"
|
||||
UnknownRequestTypeErrorMessage = "Unknown Request Type: %s"
|
||||
UnknownRequestTypeCode = "SDK.UnknownRequestType"
|
||||
UnknownRequestTypeMessage = "Unknown Request Type: %s"
|
||||
|
||||
MissingParamErrorCode = "SDK.MissingParam"
|
||||
InvalidParamErrorCode = "SDK.InvalidParam"
|
||||
|
||||
JsonUnmarshalErrorCode = "SDK.JsonUnmarshalError"
|
||||
JsonUnmarshalErrorMessage = "Failed to unmarshal response, but you can get the data via response.GetHttpStatusCode() and response.GetHttpContentString()"
|
||||
|
||||
TimeoutErrorCode = "SDK.TimeoutError"
|
||||
TimeoutErrorMessage = "The request timed out %s times(%s for retry), perhaps we should have the threshold raised a little?"
|
||||
MissingParamCode = "SDK.MissingParam"
|
||||
InvalidParamCode = "SDK.InvalidParam"
|
||||
)
|
||||
|
||||
type ClientError struct {
|
||||
@@ -60,11 +52,11 @@ func NewClientError(errorCode, message string, originErr error) Error {
|
||||
}
|
||||
|
||||
func (err *ClientError) Error() string {
|
||||
clientErrMsg := fmt.Sprintf("[%s] %s", err.errorCode, err.message)
|
||||
if err.originError != nil {
|
||||
return clientErrMsg + "\ncaused by:\n" + err.originError.Error()
|
||||
return err.originError.Error()
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
return clientErrMsg
|
||||
}
|
||||
|
||||
func (err *ClientError) OriginError() error {
|
||||
@@ -86,7 +78,3 @@ func (err *ClientError) ErrorCode() string {
|
||||
func (err *ClientError) Message() string {
|
||||
return err.message
|
||||
}
|
||||
|
||||
func (err *ClientError) String() string {
|
||||
return err.Error()
|
||||
}
|
||||
|
||||
+8
-81
@@ -14,79 +14,18 @@
|
||||
|
||||
package errors
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/jmespath/go-jmespath"
|
||||
)
|
||||
|
||||
var wrapperList = []ServerErrorWrapper{
|
||||
&SignatureDostNotMatchWrapper{},
|
||||
}
|
||||
|
||||
type ServerError struct {
|
||||
httpStatus int
|
||||
requestId string
|
||||
hostId string
|
||||
errorCode string
|
||||
recommend string
|
||||
message string
|
||||
comment string
|
||||
}
|
||||
|
||||
type ServerErrorWrapper interface {
|
||||
tryWrap(error *ServerError, wrapInfo map[string]string) (bool, *ServerError)
|
||||
}
|
||||
|
||||
func (err *ServerError) Error() string {
|
||||
return fmt.Sprintf("SDK.ServerError\nErrorCode: %s\nRecommend: %s\nRequestId: %s\nMessage: %s",
|
||||
err.errorCode, err.comment+err.recommend, err.requestId, err.message)
|
||||
}
|
||||
|
||||
func NewServerError(httpStatus int, responseContent, comment string) Error {
|
||||
result := &ServerError{
|
||||
func NewServerError(httpStatus int, errorCode, message string) Error {
|
||||
return &ServerError{
|
||||
httpStatus: httpStatus,
|
||||
message: responseContent,
|
||||
comment: comment,
|
||||
errorCode: errorCode,
|
||||
message: message,
|
||||
}
|
||||
|
||||
var data interface{}
|
||||
err := json.Unmarshal([]byte(responseContent), &data)
|
||||
if err == nil {
|
||||
requestId, _ := jmespath.Search("RequestId", data)
|
||||
hostId, _ := jmespath.Search("HostId", data)
|
||||
errorCode, _ := jmespath.Search("Code", data)
|
||||
recommend, _ := jmespath.Search("Recommend", data)
|
||||
message, _ := jmespath.Search("Message", data)
|
||||
|
||||
if requestId != nil {
|
||||
result.requestId = requestId.(string)
|
||||
}
|
||||
if hostId != nil {
|
||||
result.hostId = hostId.(string)
|
||||
}
|
||||
if errorCode != nil {
|
||||
result.errorCode = errorCode.(string)
|
||||
}
|
||||
if recommend != nil {
|
||||
result.recommend = recommend.(string)
|
||||
}
|
||||
if message != nil {
|
||||
result.message = message.(string)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func WrapServerError(originError *ServerError, wrapInfo map[string]string) *ServerError {
|
||||
for _, wrapper := range wrapperList {
|
||||
ok, newError := wrapper.tryWrap(originError, wrapInfo)
|
||||
if ok {
|
||||
return newError
|
||||
}
|
||||
}
|
||||
return originError
|
||||
}
|
||||
|
||||
func (err *ServerError) HttpStatus() int {
|
||||
@@ -101,22 +40,10 @@ func (err *ServerError) Message() string {
|
||||
return err.message
|
||||
}
|
||||
|
||||
func (err *ServerError) Error() string {
|
||||
return "SDK.ServerError"
|
||||
}
|
||||
|
||||
func (err *ServerError) OriginError() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (err *ServerError) HostId() string {
|
||||
return err.hostId
|
||||
}
|
||||
|
||||
func (err *ServerError) RequestId() string {
|
||||
return err.requestId
|
||||
}
|
||||
|
||||
func (err *ServerError) Recommend() string {
|
||||
return err.recommend
|
||||
}
|
||||
|
||||
func (err *ServerError) Comment() string {
|
||||
return err.comment
|
||||
}
|
||||
|
||||
Generated
Vendored
-29
@@ -1,29 +0,0 @@
|
||||
package errors
|
||||
|
||||
import "strings"
|
||||
|
||||
const SignatureDostNotMatchErrorCode = "SignatureDoesNotMatch"
|
||||
const MessagePrefix = "Specified signature is not matched with our calculation. server string to sign is:"
|
||||
|
||||
type SignatureDostNotMatchWrapper struct {
|
||||
}
|
||||
|
||||
func (*SignatureDostNotMatchWrapper) tryWrap(error *ServerError, wrapInfo map[string]string) (bool, *ServerError) {
|
||||
clientStringToSign := wrapInfo["StringToSign"]
|
||||
if error.errorCode == SignatureDostNotMatchErrorCode && clientStringToSign != "" {
|
||||
message := error.message
|
||||
if strings.HasPrefix(message, MessagePrefix) {
|
||||
serverStringToSign := message[len(MessagePrefix):]
|
||||
if clientStringToSign == serverStringToSign {
|
||||
// user secret is error
|
||||
error.recommend = "Please check you AccessKeySecret"
|
||||
} else {
|
||||
error.recommend = "This may be a bug with the SDK and we hope you can submit this question in the " +
|
||||
"github issue(https://github.com/aliyun/alibaba-cloud-sdk-go/issues), thanks very much"
|
||||
}
|
||||
}
|
||||
return true, error
|
||||
} else {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
+6
-28
@@ -59,7 +59,6 @@ type AcsRequest interface {
|
||||
GetPort() string
|
||||
GetRegionId() string
|
||||
GetUrl() string
|
||||
GetQueries() string
|
||||
GetHeaders() map[string]string
|
||||
GetQueryParams() map[string]string
|
||||
GetFormParams() map[string]string
|
||||
@@ -73,15 +72,10 @@ type AcsRequest interface {
|
||||
GetLocationServiceCode() string
|
||||
GetLocationEndpointType() string
|
||||
|
||||
SetStringToSign(stringToSign string)
|
||||
GetStringToSign() string
|
||||
|
||||
SetDomain(domain string)
|
||||
SetContent(content []byte)
|
||||
SetScheme(scheme string)
|
||||
BuildUrl() string
|
||||
BuildQueries() string
|
||||
|
||||
GetQueries() string
|
||||
addHeaderParam(key, value string)
|
||||
addQueryParam(key, value string)
|
||||
addFormParam(key, value string)
|
||||
@@ -96,9 +90,8 @@ type baseRequest struct {
|
||||
Port string
|
||||
RegionId string
|
||||
|
||||
product string
|
||||
version string
|
||||
|
||||
product string
|
||||
version string
|
||||
actionName string
|
||||
|
||||
AcceptFormat string
|
||||
@@ -112,8 +105,6 @@ type baseRequest struct {
|
||||
locationEndpointType string
|
||||
|
||||
queries string
|
||||
|
||||
stringToSign string
|
||||
}
|
||||
|
||||
func (request *baseRequest) GetQueryParams() map[string]string {
|
||||
@@ -172,10 +163,6 @@ func (request *baseRequest) GetScheme() string {
|
||||
return request.Scheme
|
||||
}
|
||||
|
||||
func (request *baseRequest) SetScheme(scheme string) {
|
||||
request.Scheme = scheme
|
||||
}
|
||||
|
||||
func (request *baseRequest) GetMethod() string {
|
||||
return request.Method
|
||||
}
|
||||
@@ -209,24 +196,15 @@ func (request *baseRequest) GetContentType() (contentType string, contains bool)
|
||||
return
|
||||
}
|
||||
|
||||
func (request *baseRequest) SetStringToSign(stringToSign string) {
|
||||
request.stringToSign = stringToSign
|
||||
}
|
||||
|
||||
func (request *baseRequest) GetStringToSign() string {
|
||||
return request.stringToSign
|
||||
}
|
||||
|
||||
func defaultBaseRequest() (request *baseRequest) {
|
||||
request = &baseRequest{
|
||||
Scheme: "",
|
||||
Scheme: HTTP,
|
||||
AcceptFormat: "JSON",
|
||||
Method: GET,
|
||||
QueryParams: make(map[string]string),
|
||||
Headers: map[string]string{
|
||||
"x-sdk-client": "golang/1.0.0",
|
||||
"x-sdk-invoke-type": "normal",
|
||||
"Accept-Encoding": "identity",
|
||||
},
|
||||
FormParams: make(map[string]string),
|
||||
}
|
||||
@@ -301,8 +279,8 @@ func addParam(request AcsRequest, position, name, value string) (err error) {
|
||||
case Body:
|
||||
request.addFormParam(name, value)
|
||||
default:
|
||||
errMsg := fmt.Sprintf(errors.UnsupportedParamPositionErrorMessage, position)
|
||||
err = errors.NewClientError(errors.UnsupportedParamPositionErrorCode, errMsg, nil)
|
||||
errMsg := fmt.Sprintf(errors.UnsupportedParamPositionMessage, position)
|
||||
err = errors.NewClientError(errors.UnsupportedParamPositionCode, errMsg, nil)
|
||||
}
|
||||
}
|
||||
return
|
||||
|
||||
+7
-55
@@ -1,8 +1,6 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
|
||||
"io"
|
||||
"strings"
|
||||
@@ -31,49 +29,15 @@ func NewCommonRequest() (request *CommonRequest) {
|
||||
return
|
||||
}
|
||||
|
||||
func (request *CommonRequest) String() string {
|
||||
request.TransToAcsRequest()
|
||||
request.BuildQueries()
|
||||
request.BuildUrl()
|
||||
|
||||
resultBuilder := bytes.Buffer{}
|
||||
|
||||
mapOutput := func(m map[string]string) {
|
||||
if len(m) > 0 {
|
||||
for key, value := range m {
|
||||
resultBuilder.WriteString(key + ": " + value + "\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Request Line
|
||||
resultBuilder.WriteString("\n")
|
||||
resultBuilder.WriteString(fmt.Sprintf("%s %s %s/1.1\n", request.Method, request.GetQueries(), strings.ToUpper(request.Scheme)))
|
||||
|
||||
// Headers
|
||||
resultBuilder.WriteString("Host" + ": " + request.Domain + "\n")
|
||||
mapOutput(request.Headers)
|
||||
|
||||
resultBuilder.WriteString("\n")
|
||||
// Body
|
||||
if len(request.Content) > 0 {
|
||||
resultBuilder.WriteString(string(request.Content) + "\n")
|
||||
} else {
|
||||
mapOutput(request.FormParams)
|
||||
}
|
||||
|
||||
return resultBuilder.String()
|
||||
}
|
||||
|
||||
func (request *CommonRequest) TransToAcsRequest() {
|
||||
if len(request.Version) == 0 {
|
||||
errors.NewClientError(errors.MissingParamErrorCode, "Common request [version] is required", nil)
|
||||
errors.NewClientError(errors.MissingParamCode, "Common request [version] is required", nil)
|
||||
}
|
||||
if len(request.ApiName) == 0 && len(request.PathPattern) == 0 {
|
||||
errors.NewClientError(errors.MissingParamErrorCode, "At least one of [ApiName] and [PathPattern] should has a value", nil)
|
||||
errors.NewClientError(errors.MissingParamCode, "At least one of [ApiName] and [PathPattern] should has a value", nil)
|
||||
}
|
||||
if len(request.Domain) == 0 && len(request.Product) == 0 {
|
||||
errors.NewClientError(errors.MissingParamErrorCode, "At least one of [Domain] and [Product] should has a value", nil)
|
||||
errors.NewClientError(errors.MissingParamCode, "At least one of [Domain] and [Product] should has a value", nil)
|
||||
}
|
||||
|
||||
if len(request.PathPattern) > 0 {
|
||||
@@ -91,18 +55,6 @@ func (request *CommonRequest) TransToAcsRequest() {
|
||||
|
||||
}
|
||||
|
||||
func (request *CommonRequest) BuildUrl() string {
|
||||
if len(request.Port) > 0 {
|
||||
return strings.ToLower(request.Scheme) + "://" + request.Domain + ":" + request.Port + request.BuildQueries()
|
||||
}
|
||||
|
||||
return strings.ToLower(request.Scheme) + "://" + request.Domain + request.BuildQueries()
|
||||
}
|
||||
|
||||
func (request *CommonRequest) BuildQueries() string {
|
||||
return request.Ontology.BuildQueries()
|
||||
}
|
||||
|
||||
func (request *CommonRequest) GetUrl() string {
|
||||
if len(request.Port) > 0 {
|
||||
return strings.ToLower(request.Scheme) + "://" + request.Domain + ":" + request.Port + request.GetQueries()
|
||||
@@ -111,10 +63,6 @@ func (request *CommonRequest) GetUrl() string {
|
||||
return strings.ToLower(request.Scheme) + "://" + request.Domain + request.GetQueries()
|
||||
}
|
||||
|
||||
func (request *CommonRequest) GetQueries() string {
|
||||
return request.Ontology.GetQueries()
|
||||
}
|
||||
|
||||
func (request *CommonRequest) GetBodyReader() io.Reader {
|
||||
return request.Ontology.GetBodyReader()
|
||||
}
|
||||
@@ -123,6 +71,10 @@ func (request *CommonRequest) GetStyle() string {
|
||||
return request.Ontology.GetStyle()
|
||||
}
|
||||
|
||||
func (request *CommonRequest) GetQueries() string {
|
||||
return request.Ontology.GetQueries()
|
||||
}
|
||||
|
||||
func (request *CommonRequest) addPathParam(key, value string) {
|
||||
request.PathParams[key] = value
|
||||
}
|
||||
|
||||
+7
-31
@@ -18,7 +18,6 @@ import (
|
||||
"bytes"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils"
|
||||
"io"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
@@ -45,15 +44,13 @@ func (request *RoaRequest) GetBodyReader() io.Reader {
|
||||
}
|
||||
|
||||
func (request *RoaRequest) GetQueries() string {
|
||||
if len(request.queries) == 0 {
|
||||
request.buildQueries()
|
||||
}
|
||||
return request.queries
|
||||
}
|
||||
|
||||
// for sign method, need not url encoded
|
||||
func (request *RoaRequest) BuildQueries() string {
|
||||
return request.buildQueries(false)
|
||||
}
|
||||
|
||||
func (request *RoaRequest) buildQueries(needParamEncode bool) string {
|
||||
func (request *RoaRequest) buildQueries() {
|
||||
// replace path params with value
|
||||
path := request.pathPattern
|
||||
for key, value := range request.PathParams {
|
||||
@@ -77,46 +74,25 @@ func (request *RoaRequest) buildQueries(needParamEncode bool) string {
|
||||
// append urlBuilder
|
||||
urlBuilder := bytes.Buffer{}
|
||||
urlBuilder.WriteString(path)
|
||||
if len(queryKeys) > 0 {
|
||||
urlBuilder.WriteString("?")
|
||||
}
|
||||
urlBuilder.WriteString("?")
|
||||
for i := 0; i < len(queryKeys); i++ {
|
||||
queryKey := queryKeys[i]
|
||||
urlBuilder.WriteString(queryKey)
|
||||
if value := queryParams[queryKey]; len(value) > 0 {
|
||||
urlBuilder.WriteString("=")
|
||||
if needParamEncode {
|
||||
urlBuilder.WriteString(url.QueryEscape(value))
|
||||
} else {
|
||||
urlBuilder.WriteString(value)
|
||||
}
|
||||
urlBuilder.WriteString(value)
|
||||
}
|
||||
if i < len(queryKeys)-1 {
|
||||
urlBuilder.WriteString("&")
|
||||
}
|
||||
}
|
||||
result := urlBuilder.String()
|
||||
result = popStandardUrlencode(result)
|
||||
request.queries = result
|
||||
return request.queries
|
||||
}
|
||||
|
||||
func popStandardUrlencode(stringToSign string) (result string) {
|
||||
result = strings.Replace(stringToSign, "+", "%20", -1)
|
||||
result = strings.Replace(result, "*", "%2A", -1)
|
||||
result = strings.Replace(result, "%7E", "~", -1)
|
||||
return
|
||||
request.queries = urlBuilder.String()
|
||||
}
|
||||
|
||||
func (request *RoaRequest) GetUrl() string {
|
||||
return strings.ToLower(request.Scheme) + "://" + request.Domain + ":" + request.Port + request.GetQueries()
|
||||
}
|
||||
|
||||
func (request *RoaRequest) BuildUrl() string {
|
||||
// for network trans, need url encoded
|
||||
return strings.ToLower(request.Scheme) + "://" + request.Domain + ":" + request.Port + request.buildQueries(true)
|
||||
}
|
||||
|
||||
func (request *RoaRequest) addPathParam(key, value string) {
|
||||
request.PathParams[key] = value
|
||||
}
|
||||
|
||||
+4
-9
@@ -42,20 +42,15 @@ func (request *RpcRequest) GetBodyReader() io.Reader {
|
||||
}
|
||||
}
|
||||
|
||||
func (request *RpcRequest) BuildQueries() string {
|
||||
request.queries = "/?" + utils.GetUrlFormedMap(request.QueryParams)
|
||||
return request.queries
|
||||
}
|
||||
|
||||
func (request *RpcRequest) GetQueries() string {
|
||||
if request.queries == "" {
|
||||
request.queries = "/?" + utils.GetUrlFormedMap(request.QueryParams)
|
||||
}
|
||||
return request.queries
|
||||
}
|
||||
|
||||
func (request *RpcRequest) BuildUrl() string {
|
||||
return strings.ToLower(request.Scheme) + "://" + request.Domain + ":" + request.Port + request.BuildQueries()
|
||||
}
|
||||
|
||||
func (request *RpcRequest) GetUrl() string {
|
||||
//return strings.ToLower(request.Scheme) + "://" + request.Domain + ":" + request.Port + request.GetQueries()
|
||||
return strings.ToLower(request.Scheme) + "://" + request.Domain + request.GetQueries()
|
||||
}
|
||||
|
||||
|
||||
+8
-16
@@ -4,37 +4,29 @@ import "strconv"
|
||||
|
||||
type Integer string
|
||||
|
||||
func NewInteger(integer int) Integer {
|
||||
return Integer(strconv.Itoa(integer))
|
||||
func NewInteger(n int) Integer {
|
||||
return Integer(strconv.Itoa(n))
|
||||
}
|
||||
|
||||
func (integer Integer) HasValue() bool {
|
||||
func (integer Integer) hasValue() bool {
|
||||
return integer != ""
|
||||
}
|
||||
|
||||
func (integer Integer) GetValue() (int, error) {
|
||||
func (integer Integer) getValue() (int, error) {
|
||||
return strconv.Atoi(string(integer))
|
||||
}
|
||||
|
||||
func NewInteger64(integer int64) Integer {
|
||||
return Integer(strconv.FormatInt(integer, 10))
|
||||
}
|
||||
|
||||
func (integer Integer) GetValue64() (int64, error) {
|
||||
return strconv.ParseInt(string(integer), 10, 0)
|
||||
}
|
||||
|
||||
type Boolean string
|
||||
|
||||
func NewBoolean(bool bool) Boolean {
|
||||
return Boolean(strconv.FormatBool(bool))
|
||||
}
|
||||
|
||||
func (boolean Boolean) HasValue() bool {
|
||||
func (boolean Boolean) hasValue() bool {
|
||||
return boolean != ""
|
||||
}
|
||||
|
||||
func (boolean Boolean) GetValue() (bool, error) {
|
||||
func (boolean Boolean) getValue() (bool, error) {
|
||||
return strconv.ParseBool(string(boolean))
|
||||
}
|
||||
|
||||
@@ -44,10 +36,10 @@ func NewFloat(f float64) Float {
|
||||
return Float(strconv.FormatFloat(f, 'f', 6, 64))
|
||||
}
|
||||
|
||||
func (float Float) HasValue() bool {
|
||||
func (float Float) hasValue() bool {
|
||||
return float != ""
|
||||
}
|
||||
|
||||
func (float Float) GetValue() (float64, error) {
|
||||
func (float Float) getValue() (float64, error) {
|
||||
return strconv.ParseFloat(string(float), 64)
|
||||
}
|
||||
|
||||
-341
@@ -1,341 +0,0 @@
|
||||
package responses
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/json-iterator/go"
|
||||
"io"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const maxUint = ^uint(0)
|
||||
const maxInt = int(maxUint >> 1)
|
||||
const minInt = -maxInt - 1
|
||||
|
||||
var jsonParser jsoniter.API
|
||||
var initJson = &sync.Once{}
|
||||
|
||||
func initJsonParserOnce() {
|
||||
initJson.Do(func() {
|
||||
registerBetterFuzzyDecoder()
|
||||
jsonParser = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
})
|
||||
}
|
||||
|
||||
func registerBetterFuzzyDecoder() {
|
||||
jsoniter.RegisterTypeDecoder("string", &nullableFuzzyStringDecoder{})
|
||||
jsoniter.RegisterTypeDecoder("bool", &fuzzyBoolDecoder{})
|
||||
jsoniter.RegisterTypeDecoder("float32", &nullableFuzzyFloat32Decoder{})
|
||||
jsoniter.RegisterTypeDecoder("float64", &nullableFuzzyFloat64Decoder{})
|
||||
jsoniter.RegisterTypeDecoder("int", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
if isFloat {
|
||||
val := iter.ReadFloat64()
|
||||
if val > float64(maxInt) || val < float64(minInt) {
|
||||
iter.ReportError("fuzzy decode int", "exceed range")
|
||||
return
|
||||
}
|
||||
*((*int)(ptr)) = int(val)
|
||||
} else {
|
||||
*((*int)(ptr)) = iter.ReadInt()
|
||||
}
|
||||
}})
|
||||
jsoniter.RegisterTypeDecoder("uint", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
if isFloat {
|
||||
val := iter.ReadFloat64()
|
||||
if val > float64(maxUint) || val < 0 {
|
||||
iter.ReportError("fuzzy decode uint", "exceed range")
|
||||
return
|
||||
}
|
||||
*((*uint)(ptr)) = uint(val)
|
||||
} else {
|
||||
*((*uint)(ptr)) = iter.ReadUint()
|
||||
}
|
||||
}})
|
||||
jsoniter.RegisterTypeDecoder("int8", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
if isFloat {
|
||||
val := iter.ReadFloat64()
|
||||
if val > float64(math.MaxInt8) || val < float64(math.MinInt8) {
|
||||
iter.ReportError("fuzzy decode int8", "exceed range")
|
||||
return
|
||||
}
|
||||
*((*int8)(ptr)) = int8(val)
|
||||
} else {
|
||||
*((*int8)(ptr)) = iter.ReadInt8()
|
||||
}
|
||||
}})
|
||||
jsoniter.RegisterTypeDecoder("uint8", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
if isFloat {
|
||||
val := iter.ReadFloat64()
|
||||
if val > float64(math.MaxUint8) || val < 0 {
|
||||
iter.ReportError("fuzzy decode uint8", "exceed range")
|
||||
return
|
||||
}
|
||||
*((*uint8)(ptr)) = uint8(val)
|
||||
} else {
|
||||
*((*uint8)(ptr)) = iter.ReadUint8()
|
||||
}
|
||||
}})
|
||||
jsoniter.RegisterTypeDecoder("int16", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
if isFloat {
|
||||
val := iter.ReadFloat64()
|
||||
if val > float64(math.MaxInt16) || val < float64(math.MinInt16) {
|
||||
iter.ReportError("fuzzy decode int16", "exceed range")
|
||||
return
|
||||
}
|
||||
*((*int16)(ptr)) = int16(val)
|
||||
} else {
|
||||
*((*int16)(ptr)) = iter.ReadInt16()
|
||||
}
|
||||
}})
|
||||
jsoniter.RegisterTypeDecoder("uint16", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
if isFloat {
|
||||
val := iter.ReadFloat64()
|
||||
if val > float64(math.MaxUint16) || val < 0 {
|
||||
iter.ReportError("fuzzy decode uint16", "exceed range")
|
||||
return
|
||||
}
|
||||
*((*uint16)(ptr)) = uint16(val)
|
||||
} else {
|
||||
*((*uint16)(ptr)) = iter.ReadUint16()
|
||||
}
|
||||
}})
|
||||
jsoniter.RegisterTypeDecoder("int32", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
if isFloat {
|
||||
val := iter.ReadFloat64()
|
||||
if val > float64(math.MaxInt32) || val < float64(math.MinInt32) {
|
||||
iter.ReportError("fuzzy decode int32", "exceed range")
|
||||
return
|
||||
}
|
||||
*((*int32)(ptr)) = int32(val)
|
||||
} else {
|
||||
*((*int32)(ptr)) = iter.ReadInt32()
|
||||
}
|
||||
}})
|
||||
jsoniter.RegisterTypeDecoder("uint32", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
if isFloat {
|
||||
val := iter.ReadFloat64()
|
||||
if val > float64(math.MaxUint32) || val < 0 {
|
||||
iter.ReportError("fuzzy decode uint32", "exceed range")
|
||||
return
|
||||
}
|
||||
*((*uint32)(ptr)) = uint32(val)
|
||||
} else {
|
||||
*((*uint32)(ptr)) = iter.ReadUint32()
|
||||
}
|
||||
}})
|
||||
jsoniter.RegisterTypeDecoder("int64", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
if isFloat {
|
||||
val := iter.ReadFloat64()
|
||||
if val > float64(math.MaxInt64) || val < float64(math.MinInt64) {
|
||||
iter.ReportError("fuzzy decode int64", "exceed range")
|
||||
return
|
||||
}
|
||||
*((*int64)(ptr)) = int64(val)
|
||||
} else {
|
||||
*((*int64)(ptr)) = iter.ReadInt64()
|
||||
}
|
||||
}})
|
||||
jsoniter.RegisterTypeDecoder("uint64", &nullableFuzzyIntegerDecoder{func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
if isFloat {
|
||||
val := iter.ReadFloat64()
|
||||
if val > float64(math.MaxUint64) || val < 0 {
|
||||
iter.ReportError("fuzzy decode uint64", "exceed range")
|
||||
return
|
||||
}
|
||||
*((*uint64)(ptr)) = uint64(val)
|
||||
} else {
|
||||
*((*uint64)(ptr)) = iter.ReadUint64()
|
||||
}
|
||||
}})
|
||||
}
|
||||
|
||||
type nullableFuzzyStringDecoder struct {
|
||||
}
|
||||
|
||||
func (decoder *nullableFuzzyStringDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
valueType := iter.WhatIsNext()
|
||||
switch valueType {
|
||||
case jsoniter.NumberValue:
|
||||
var number json.Number
|
||||
iter.ReadVal(&number)
|
||||
*((*string)(ptr)) = string(number)
|
||||
case jsoniter.StringValue:
|
||||
*((*string)(ptr)) = iter.ReadString()
|
||||
case jsoniter.BoolValue:
|
||||
*((*string)(ptr)) = strconv.FormatBool(iter.ReadBool())
|
||||
case jsoniter.NilValue:
|
||||
iter.ReadNil()
|
||||
*((*string)(ptr)) = ""
|
||||
default:
|
||||
iter.ReportError("fuzzyStringDecoder", "not number or string or bool")
|
||||
}
|
||||
}
|
||||
|
||||
type fuzzyBoolDecoder struct {
|
||||
}
|
||||
|
||||
func (decoder *fuzzyBoolDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
valueType := iter.WhatIsNext()
|
||||
switch valueType {
|
||||
case jsoniter.BoolValue:
|
||||
*((*bool)(ptr)) = iter.ReadBool()
|
||||
case jsoniter.NumberValue:
|
||||
var number json.Number
|
||||
iter.ReadVal(&number)
|
||||
num, err := number.Int64()
|
||||
if err != nil {
|
||||
iter.ReportError("fuzzyBoolDecoder", "get value from json.number failed")
|
||||
}
|
||||
if num == 0 {
|
||||
*((*bool)(ptr)) = false
|
||||
} else {
|
||||
*((*bool)(ptr)) = true
|
||||
}
|
||||
case jsoniter.StringValue:
|
||||
strValue := strings.ToLower(iter.ReadString())
|
||||
if strValue == "true" {
|
||||
*((*bool)(ptr)) = true
|
||||
} else if strValue == "false" || strValue == "" {
|
||||
*((*bool)(ptr)) = false
|
||||
} else {
|
||||
iter.ReportError("fuzzyBoolDecoder", "unsupported bool value: "+strValue)
|
||||
}
|
||||
case jsoniter.NilValue:
|
||||
iter.ReadNil()
|
||||
*((*bool)(ptr)) = false
|
||||
default:
|
||||
iter.ReportError("fuzzyBoolDecoder", "not number or string or nil")
|
||||
}
|
||||
}
|
||||
|
||||
type tolerateEmptyArrayDecoder struct {
|
||||
valDecoder jsoniter.ValDecoder
|
||||
}
|
||||
|
||||
func (decoder *tolerateEmptyArrayDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
if iter.WhatIsNext() == jsoniter.ArrayValue {
|
||||
iter.Skip()
|
||||
newIter := iter.Pool().BorrowIterator([]byte("{}"))
|
||||
defer iter.Pool().ReturnIterator(newIter)
|
||||
decoder.valDecoder.Decode(ptr, newIter)
|
||||
} else {
|
||||
decoder.valDecoder.Decode(ptr, iter)
|
||||
}
|
||||
}
|
||||
|
||||
type nullableFuzzyIntegerDecoder struct {
|
||||
fun func(isFloat bool, ptr unsafe.Pointer, iter *jsoniter.Iterator)
|
||||
}
|
||||
|
||||
func (decoder *nullableFuzzyIntegerDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
valueType := iter.WhatIsNext()
|
||||
var str string
|
||||
switch valueType {
|
||||
case jsoniter.NumberValue:
|
||||
var number json.Number
|
||||
iter.ReadVal(&number)
|
||||
str = string(number)
|
||||
case jsoniter.StringValue:
|
||||
str = iter.ReadString()
|
||||
// support empty string
|
||||
if str == "" {
|
||||
str = "0"
|
||||
}
|
||||
case jsoniter.BoolValue:
|
||||
if iter.ReadBool() {
|
||||
str = "1"
|
||||
} else {
|
||||
str = "0"
|
||||
}
|
||||
case jsoniter.NilValue:
|
||||
iter.ReadNil()
|
||||
str = "0"
|
||||
default:
|
||||
iter.ReportError("fuzzyIntegerDecoder", "not number or string")
|
||||
}
|
||||
newIter := iter.Pool().BorrowIterator([]byte(str))
|
||||
defer iter.Pool().ReturnIterator(newIter)
|
||||
isFloat := strings.IndexByte(str, '.') != -1
|
||||
decoder.fun(isFloat, ptr, newIter)
|
||||
if newIter.Error != nil && newIter.Error != io.EOF {
|
||||
iter.Error = newIter.Error
|
||||
}
|
||||
}
|
||||
|
||||
type nullableFuzzyFloat32Decoder struct {
|
||||
}
|
||||
|
||||
func (decoder *nullableFuzzyFloat32Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
valueType := iter.WhatIsNext()
|
||||
var str string
|
||||
switch valueType {
|
||||
case jsoniter.NumberValue:
|
||||
*((*float32)(ptr)) = iter.ReadFloat32()
|
||||
case jsoniter.StringValue:
|
||||
str = iter.ReadString()
|
||||
// support empty string
|
||||
if str == "" {
|
||||
*((*float32)(ptr)) = 0
|
||||
return
|
||||
}
|
||||
newIter := iter.Pool().BorrowIterator([]byte(str))
|
||||
defer iter.Pool().ReturnIterator(newIter)
|
||||
*((*float32)(ptr)) = newIter.ReadFloat32()
|
||||
if newIter.Error != nil && newIter.Error != io.EOF {
|
||||
iter.Error = newIter.Error
|
||||
}
|
||||
case jsoniter.BoolValue:
|
||||
// support bool to float32
|
||||
if iter.ReadBool() {
|
||||
*((*float32)(ptr)) = 1
|
||||
} else {
|
||||
*((*float32)(ptr)) = 0
|
||||
}
|
||||
case jsoniter.NilValue:
|
||||
iter.ReadNil()
|
||||
*((*float32)(ptr)) = 0
|
||||
default:
|
||||
iter.ReportError("nullableFuzzyFloat32Decoder", "not number or string")
|
||||
}
|
||||
}
|
||||
|
||||
type nullableFuzzyFloat64Decoder struct {
|
||||
}
|
||||
|
||||
func (decoder *nullableFuzzyFloat64Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
valueType := iter.WhatIsNext()
|
||||
var str string
|
||||
switch valueType {
|
||||
case jsoniter.NumberValue:
|
||||
*((*float64)(ptr)) = iter.ReadFloat64()
|
||||
case jsoniter.StringValue:
|
||||
str = iter.ReadString()
|
||||
// support empty string
|
||||
if str == "" {
|
||||
*((*float64)(ptr)) = 0
|
||||
return
|
||||
}
|
||||
newIter := iter.Pool().BorrowIterator([]byte(str))
|
||||
defer iter.Pool().ReturnIterator(newIter)
|
||||
*((*float64)(ptr)) = newIter.ReadFloat64()
|
||||
if newIter.Error != nil && newIter.Error != io.EOF {
|
||||
iter.Error = newIter.Error
|
||||
}
|
||||
case jsoniter.BoolValue:
|
||||
// support bool to float64
|
||||
if iter.ReadBool() {
|
||||
*((*float64)(ptr)) = 1
|
||||
} else {
|
||||
*((*float64)(ptr)) = 0
|
||||
}
|
||||
case jsoniter.NilValue:
|
||||
// support empty string
|
||||
iter.ReadNil()
|
||||
*((*float64)(ptr)) = 0
|
||||
default:
|
||||
iter.ReportError("nullableFuzzyFloat32Decoder", "not number or string")
|
||||
}
|
||||
}
|
||||
+9
-29
@@ -16,16 +16,15 @@ package responses
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type AcsResponse interface {
|
||||
IsSuccess() bool
|
||||
GetHttpStatus() int
|
||||
GetHttpHeaders() map[string][]string
|
||||
GetHttpContentString() string
|
||||
@@ -39,25 +38,8 @@ func Unmarshal(response AcsResponse, httpResponse *http.Response, format string)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !response.IsSuccess() {
|
||||
err = errors.NewServerError(response.GetHttpStatus(), response.GetHttpContentString(), "")
|
||||
return
|
||||
}
|
||||
if _, isCommonResponse := response.(CommonResponse); isCommonResponse {
|
||||
// common response need not unmarshal
|
||||
return
|
||||
}
|
||||
|
||||
if len(response.GetHttpContentBytes()) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if strings.ToUpper(format) == "JSON" {
|
||||
initJsonParserOnce()
|
||||
err = jsonParser.Unmarshal(response.GetHttpContentBytes(), response)
|
||||
if err != nil {
|
||||
err = errors.NewClientError(errors.JsonUnmarshalErrorCode, errors.JsonUnmarshalErrorMessage, err)
|
||||
}
|
||||
err = json.Unmarshal(response.GetHttpContentBytes(), response)
|
||||
} else if strings.ToUpper(format) == "XML" {
|
||||
err = xml.Unmarshal(response.GetHttpContentBytes(), response)
|
||||
}
|
||||
@@ -117,17 +99,15 @@ func (baseResponse *BaseResponse) parseFromHttpResponse(httpResponse *http.Respo
|
||||
func (baseResponse *BaseResponse) String() string {
|
||||
resultBuilder := bytes.Buffer{}
|
||||
// statusCode
|
||||
resultBuilder.WriteString("\n")
|
||||
resultBuilder.WriteString(fmt.Sprintf("%s %s\n", baseResponse.originHttpResponse.Proto, baseResponse.originHttpResponse.Status))
|
||||
resultBuilder.WriteString("StatusCode : " + strconv.Itoa(baseResponse.httpStatus) + "\n")
|
||||
// httpHeaders
|
||||
//resultBuilder.WriteString("Headers:\n")
|
||||
resultBuilder.WriteString("Headers:\n")
|
||||
for key, value := range baseResponse.httpHeaders {
|
||||
resultBuilder.WriteString(key + ": " + strings.Join(value, ";") + "\n")
|
||||
resultBuilder.WriteString(" -> " + key + " : " + strings.Join(value, ";") + "\n")
|
||||
}
|
||||
resultBuilder.WriteString("\n")
|
||||
// content
|
||||
//resultBuilder.WriteString("Content:\n")
|
||||
resultBuilder.WriteString(baseResponse.httpContentString + "\n")
|
||||
resultBuilder.WriteString("Content:\n")
|
||||
resultBuilder.WriteString(" -> " + baseResponse.httpContentString + "\n")
|
||||
return resultBuilder.String()
|
||||
}
|
||||
|
||||
@@ -135,7 +115,7 @@ type CommonResponse struct {
|
||||
*BaseResponse
|
||||
}
|
||||
|
||||
func NewCommonResponse() (response *CommonResponse) {
|
||||
func NewCommonResponse() (request *CommonResponse) {
|
||||
return &CommonResponse{
|
||||
BaseResponse: &BaseResponse{},
|
||||
}
|
||||
|
||||
+2
-19
@@ -27,10 +27,6 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// if you use go 1.10 or higher, you can hack this util by these to avoid "TimeZone.zip not found" on Windows
|
||||
var LoadLocationFromTZData func(name string, data []byte) (*time.Location, error) = nil
|
||||
var TZData []byte = nil
|
||||
|
||||
func GetUUIDV4() (uuidHex string) {
|
||||
uuidV4 := uuid.NewV4()
|
||||
uuidHex = hex.EncodeToString(uuidV4.Bytes())
|
||||
@@ -45,17 +41,8 @@ func GetMD5Base64(bytes []byte) (base64Value string) {
|
||||
return
|
||||
}
|
||||
|
||||
func GetGMTLocation() (*time.Location, error) {
|
||||
if LoadLocationFromTZData != nil && TZData != nil {
|
||||
return LoadLocationFromTZData("GMT", TZData)
|
||||
} else {
|
||||
return time.LoadLocation("GMT")
|
||||
}
|
||||
}
|
||||
|
||||
func GetTimeInFormatISO8601() (timeStr string) {
|
||||
gmt, err := GetGMTLocation()
|
||||
|
||||
gmt, err := time.LoadLocation("GMT")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -63,8 +50,7 @@ func GetTimeInFormatISO8601() (timeStr string) {
|
||||
}
|
||||
|
||||
func GetTimeInFormatRFC2616() (timeStr string) {
|
||||
gmt, err := GetGMTLocation()
|
||||
|
||||
gmt, err := time.LoadLocation("GMT")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -104,9 +90,6 @@ func InitStructWithDefaultTag(bean interface{}) {
|
||||
case "int":
|
||||
intValue, _ := strconv.ParseInt(defaultValue, 10, 64)
|
||||
setter.SetInt(intValue)
|
||||
case "time.Duration":
|
||||
intValue, _ := strconv.ParseInt(defaultValue, 10, 64)
|
||||
setter.SetInt(intValue)
|
||||
case "string":
|
||||
setter.SetString(defaultValue)
|
||||
case "bool":
|
||||
|
||||
+2
-3
@@ -21,7 +21,6 @@ package thrift
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -458,8 +457,8 @@ func (p *TBinaryProtocol) ReadBinary() ([]byte, error) {
|
||||
return buf, NewTProtocolException(err)
|
||||
}
|
||||
|
||||
func (p *TBinaryProtocol) Flush(ctx context.Context) (err error) {
|
||||
return NewTProtocolException(p.trans.Flush(ctx))
|
||||
func (p *TBinaryProtocol) Flush() (err error) {
|
||||
return NewTProtocolException(p.trans.Flush())
|
||||
}
|
||||
|
||||
func (p *TBinaryProtocol) Skip(fieldType TType) (err error) {
|
||||
|
||||
+2
-3
@@ -21,7 +21,6 @@ package thrift
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
)
|
||||
|
||||
type TBufferedTransportFactory struct {
|
||||
@@ -79,12 +78,12 @@ func (p *TBufferedTransport) Write(b []byte) (int, error) {
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (p *TBufferedTransport) Flush(ctx context.Context) error {
|
||||
func (p *TBufferedTransport) Flush() error {
|
||||
if err := p.ReadWriter.Flush(); err != nil {
|
||||
p.ReadWriter.Writer.Reset(p.tp)
|
||||
return err
|
||||
}
|
||||
return p.tp.Flush(ctx)
|
||||
return p.tp.Flush()
|
||||
}
|
||||
|
||||
func (p *TBufferedTransport) RemainingBytes() (num_bytes uint64) {
|
||||
|
||||
+5
-12
@@ -1,13 +1,6 @@
|
||||
package thrift
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type TClient interface {
|
||||
Call(ctx context.Context, method string, args, result TStruct) error
|
||||
}
|
||||
import "fmt"
|
||||
|
||||
type TStandardClient struct {
|
||||
seqId int32
|
||||
@@ -23,7 +16,7 @@ func NewTStandardClient(inputProtocol, outputProtocol TProtocol) *TStandardClien
|
||||
}
|
||||
}
|
||||
|
||||
func (p *TStandardClient) Send(ctx context.Context, oprot TProtocol, seqId int32, method string, args TStruct) error {
|
||||
func (p *TStandardClient) Send(oprot TProtocol, seqId int32, method string, args TStruct) error {
|
||||
if err := oprot.WriteMessageBegin(method, CALL, seqId); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -33,7 +26,7 @@ func (p *TStandardClient) Send(ctx context.Context, oprot TProtocol, seqId int32
|
||||
if err := oprot.WriteMessageEnd(); err != nil {
|
||||
return err
|
||||
}
|
||||
return oprot.Flush(ctx)
|
||||
return oprot.Flush()
|
||||
}
|
||||
|
||||
func (p *TStandardClient) Recv(iprot TProtocol, seqId int32, method string, result TStruct) error {
|
||||
@@ -68,11 +61,11 @@ func (p *TStandardClient) Recv(iprot TProtocol, seqId int32, method string, resu
|
||||
return iprot.ReadMessageEnd()
|
||||
}
|
||||
|
||||
func (p *TStandardClient) Call(ctx context.Context, method string, args, result TStruct) error {
|
||||
func (p *TStandardClient) call(method string, args, result TStruct) error {
|
||||
p.seqId++
|
||||
seqId := p.seqId
|
||||
|
||||
if err := p.Send(ctx, p.oprot, seqId, method, args); err != nil {
|
||||
if err := p.Send(p.oprot, seqId, method, args); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// +build go1.7
|
||||
|
||||
package thrift
|
||||
|
||||
import "context"
|
||||
|
||||
type TClient interface {
|
||||
Call(ctx context.Context, method string, args, result TStruct) error
|
||||
}
|
||||
|
||||
func (p *TStandardClient) Call(ctx context.Context, method string, args, result TStruct) error {
|
||||
return p.call(method, args, result)
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// +build !go1.7
|
||||
|
||||
package thrift
|
||||
|
||||
import "golang.org/x/net/context"
|
||||
|
||||
type TClient interface {
|
||||
Call(ctx context.Context, method string, args, result TStruct) error
|
||||
}
|
||||
|
||||
func (p *TStandardClient) Call(ctx context.Context, method string, args, result TStruct) error {
|
||||
return p.call(method, args, result)
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
// +build go1.7
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 thrift
|
||||
|
||||
import "context"
|
||||
|
||||
type mockProcessor struct {
|
||||
ProcessFunc func(in, out TProtocol) (bool, TException)
|
||||
}
|
||||
|
||||
func (m *mockProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) {
|
||||
return m.ProcessFunc(in, out)
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
// +build !go1.7
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 thrift
|
||||
|
||||
import "golang.org/x/net/context"
|
||||
|
||||
type mockProcessor struct {
|
||||
ProcessFunc func(in, out TProtocol) (bool, TException)
|
||||
}
|
||||
|
||||
func (m *mockProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) {
|
||||
return m.ProcessFunc(in, out)
|
||||
}
|
||||
+3
-4
@@ -20,7 +20,6 @@
|
||||
package thrift
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -600,8 +599,8 @@ func (p *TCompactProtocol) ReadBinary() (value []byte, err error) {
|
||||
return buf, NewTProtocolException(e)
|
||||
}
|
||||
|
||||
func (p *TCompactProtocol) Flush(ctx context.Context) (err error) {
|
||||
return NewTProtocolException(p.trans.Flush(ctx))
|
||||
func (p *TCompactProtocol) Flush() (err error) {
|
||||
return NewTProtocolException(p.trans.Flush())
|
||||
}
|
||||
|
||||
func (p *TCompactProtocol) Skip(fieldType TType) (err error) {
|
||||
@@ -807,7 +806,7 @@ func (p *TCompactProtocol) getTType(t tCompactType) (TType, error) {
|
||||
case COMPACT_STRUCT:
|
||||
return STRUCT, nil
|
||||
}
|
||||
return STOP, TException(fmt.Errorf("don't know what type: %v", t&0x0f))
|
||||
return STOP, TException(fmt.Errorf("don't know what type: %s", t&0x0f))
|
||||
}
|
||||
|
||||
// Given a TType value, find the appropriate TCompactProtocol.Types constant.
|
||||
|
||||
+2
-3
@@ -20,7 +20,6 @@
|
||||
package thrift
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
)
|
||||
|
||||
@@ -259,8 +258,8 @@ func (tdp *TDebugProtocol) Skip(fieldType TType) (err error) {
|
||||
log.Printf("%sSkip(fieldType=%#v) (err=%#v)", tdp.LogPrefix, fieldType, err)
|
||||
return
|
||||
}
|
||||
func (tdp *TDebugProtocol) Flush(ctx context.Context) (err error) {
|
||||
err = tdp.Delegate.Flush(ctx)
|
||||
func (tdp *TDebugProtocol) Flush() (err error) {
|
||||
err = tdp.Delegate.Flush()
|
||||
log.Printf("%sFlush() (err=%#v)", tdp.LogPrefix, err)
|
||||
return
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user