kvm.go 64 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package regiondrivers
  15. import (
  16. "context"
  17. "database/sql"
  18. "fmt"
  19. "sort"
  20. "strconv"
  21. "strings"
  22. "yunion.io/x/cloudmux/pkg/cloudprovider"
  23. "yunion.io/x/jsonutils"
  24. "yunion.io/x/log"
  25. "yunion.io/x/pkg/errors"
  26. "yunion.io/x/pkg/util/httputils"
  27. randutil "yunion.io/x/pkg/util/rand"
  28. "yunion.io/x/pkg/util/regutils"
  29. "yunion.io/x/pkg/util/secrules"
  30. "yunion.io/x/pkg/util/sets"
  31. "yunion.io/x/pkg/utils"
  32. "yunion.io/x/sqlchemy"
  33. "yunion.io/x/onecloud/pkg/apis"
  34. billing_api "yunion.io/x/onecloud/pkg/apis/billing"
  35. api "yunion.io/x/onecloud/pkg/apis/compute"
  36. hostapi "yunion.io/x/onecloud/pkg/apis/host"
  37. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  38. "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
  39. "yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
  40. "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
  41. "yunion.io/x/onecloud/pkg/cloudcommon/validators"
  42. "yunion.io/x/onecloud/pkg/compute/models"
  43. "yunion.io/x/onecloud/pkg/httperrors"
  44. "yunion.io/x/onecloud/pkg/mcclient"
  45. )
  46. type SKVMRegionDriver struct {
  47. SBaseRegionDriver
  48. }
  49. func init() {
  50. driver := SKVMRegionDriver{}
  51. models.RegisterRegionDriver(&driver)
  52. }
  53. func RunValidators(ctx context.Context, validators map[string]validators.IValidator, data *jsonutils.JSONDict, optional bool) error {
  54. for _, v := range validators {
  55. if optional {
  56. v.Optional(true)
  57. }
  58. if err := v.Validate(ctx, data); err != nil {
  59. return err
  60. }
  61. }
  62. return nil
  63. }
  64. func (self *SKVMRegionDriver) GetProvider() string {
  65. return api.CLOUD_PROVIDER_ONECLOUD
  66. }
  67. func (self *SKVMRegionDriver) ValidateCreateSecurityGroupInput(ctx context.Context, userCred mcclient.TokenCredential, input *api.SSecgroupCreateInput) (*api.SSecgroupCreateInput, error) {
  68. for i := range input.Rules {
  69. err := input.Rules[i].Check()
  70. if err != nil {
  71. return input, httperrors.NewInputParameterError("rule %d is invalid: %s", i, err)
  72. }
  73. }
  74. return input, nil
  75. }
  76. func (self *SKVMRegionDriver) ValidateCreateLoadbalancerData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, input *api.LoadbalancerCreateInput) (*api.LoadbalancerCreateInput, error) {
  77. // find available networks
  78. var network *models.SNetwork = nil
  79. if len(input.NetworkId) > 0 {
  80. netObj, err := validators.ValidateModel(ctx, userCred, models.NetworkManager, &input.NetworkId)
  81. if err != nil {
  82. return nil, err
  83. }
  84. network = netObj.(*models.SNetwork)
  85. } else if len(input.VpcId) > 0 {
  86. vpcObj, err := validators.ValidateModel(ctx, userCred, models.VpcManager, &input.VpcId)
  87. if err != nil {
  88. return nil, err
  89. }
  90. vpc := vpcObj.(*models.SVpc)
  91. networks, err := vpc.GetNetworks()
  92. if err != nil {
  93. return nil, httperrors.NewGeneralError(err)
  94. }
  95. networksLen := len(networks)
  96. if networksLen > 0 {
  97. i := randutil.Intn(networksLen)
  98. j := (i + 1) % networksLen
  99. for {
  100. net := &networks[j]
  101. addrCount, err := net.GetFreeAddressCount()
  102. if err != nil {
  103. continue
  104. }
  105. if addrCount > 0 {
  106. network = net
  107. break
  108. }
  109. j = (j + 1) % networksLen
  110. if j == i {
  111. break
  112. }
  113. }
  114. }
  115. if network == nil {
  116. return nil, httperrors.NewBadRequestError("no usable network in vpc %s(%s)", vpc.Name, vpc.Id)
  117. }
  118. } else {
  119. return nil, httperrors.NewMissingParameterError("network_id")
  120. }
  121. if network.ServerType != api.NETWORK_TYPE_GUEST {
  122. return nil, httperrors.NewBadRequestError("only network type %q is allowed", api.NETWORK_TYPE_GUEST)
  123. }
  124. if len(input.ClusterId) > 0 {
  125. clusterObj, err := validators.ValidateModel(ctx, userCred, models.LoadbalancerClusterManager, &input.ClusterId)
  126. if err != nil {
  127. return nil, err
  128. }
  129. cluster := clusterObj.(*models.SLoadbalancerCluster)
  130. input.ZoneId = cluster.ZoneId
  131. if cluster.WireId != "" && cluster.WireId != network.WireId {
  132. return nil, httperrors.NewInputParameterError("cluster wire affiliation does not match network's: %s != %s",
  133. cluster.WireId, network.WireId)
  134. }
  135. } else {
  136. if len(input.ZoneId) == 0 {
  137. return nil, httperrors.NewMissingParameterError("zone_id")
  138. }
  139. clusters := models.LoadbalancerClusterManager.FindByZoneId(input.ZoneId)
  140. if len(clusters) == 0 {
  141. return nil, httperrors.NewInputParameterError("zone %s has no lbcluster", input.ZoneId)
  142. }
  143. var (
  144. wireMatched []*models.SLoadbalancerCluster
  145. wireNeutral []*models.SLoadbalancerCluster
  146. )
  147. for i := range clusters {
  148. c := &clusters[i]
  149. if c.WireId != "" {
  150. if c.WireId == network.WireId {
  151. wireMatched = append(wireMatched, c)
  152. }
  153. } else {
  154. wireNeutral = append(wireNeutral, c)
  155. }
  156. }
  157. var choices []*models.SLoadbalancerCluster
  158. if len(wireMatched) > 0 {
  159. choices = wireMatched
  160. } else if len(wireNeutral) > 0 {
  161. choices = wireNeutral
  162. } else {
  163. return nil, httperrors.NewInputParameterError("no viable lbcluster")
  164. }
  165. i := randutil.Intn(len(choices))
  166. input.ClusterId = choices[i].Id
  167. }
  168. input.NetworkType = api.LB_NETWORK_TYPE_VPC
  169. if input.VpcId == api.DEFAULT_VPC_ID {
  170. input.NetworkType = api.LB_NETWORK_TYPE_CLASSIC
  171. }
  172. return input, nil
  173. }
  174. func (self *SKVMRegionDriver) ValidateCreateLoadbalancerBackendGroupData(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, input *api.LoadbalancerBackendGroupCreateInput) (*api.LoadbalancerBackendGroupCreateInput, error) {
  175. return input, nil
  176. }
  177. func (self *SKVMRegionDriver) ValidateCreateLoadbalancerBackendData(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, lbbg *models.SLoadbalancerBackendGroup, input *api.LoadbalancerBackendCreateInput) (*api.LoadbalancerBackendCreateInput, error) {
  178. return input, nil
  179. }
  180. func (self *SKVMRegionDriver) ValidateUpdateLoadbalancerBackendData(ctx context.Context, userCred mcclient.TokenCredential, lbbg *models.SLoadbalancerBackendGroup, input *api.LoadbalancerBackendUpdateInput) (*api.LoadbalancerBackendUpdateInput, error) {
  181. return input, nil
  182. }
  183. func (self *SKVMRegionDriver) IsSupportLoadbalancerListenerRuleRedirect() bool {
  184. return true
  185. }
  186. func (self *SKVMRegionDriver) ValidateCreateLoadbalancerListenerRuleData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, input *api.LoadbalancerListenerRuleCreateInput) (*api.LoadbalancerListenerRuleCreateInput, error) {
  187. return input, nil
  188. }
  189. func (self *SKVMRegionDriver) ValidateUpdateLoadbalancerListenerRuleData(ctx context.Context, userCred mcclient.TokenCredential, input *api.LoadbalancerListenerRuleUpdateInput) (*api.LoadbalancerListenerRuleUpdateInput, error) {
  190. return input, nil
  191. }
  192. func (self *SKVMRegionDriver) ValidateCreateLoadbalancerListenerData(ctx context.Context, userCred mcclient.TokenCredential,
  193. ownerId mcclient.IIdentityProvider, input *api.LoadbalancerListenerCreateInput,
  194. lb *models.SLoadbalancer, lbbg *models.SLoadbalancerBackendGroup) (*api.LoadbalancerListenerCreateInput, error) {
  195. return input, nil
  196. }
  197. func (self *SKVMRegionDriver) ValidateUpdateLoadbalancerListenerData(ctx context.Context, userCred mcclient.TokenCredential,
  198. lblis *models.SLoadbalancerListener, input *api.LoadbalancerListenerUpdateInput) (*api.LoadbalancerListenerUpdateInput, error) {
  199. /*
  200. certV := validators.NewModelIdOrNameValidator("certificate", "loadbalancercertificate", ownerId)
  201. tlsCipherPolicyV := validators.NewStringChoicesValidator("tls_cipher_policy", api.LB_TLS_CIPHER_POLICIES).Default(api.LB_TLS_CIPHER_POLICY_1_2)
  202. keyV := map[string]validators.IValidator{
  203. "send_proxy": validators.NewStringChoicesValidator("send_proxy", api.LB_SENDPROXY_CHOICES),
  204. "acl_status": aclStatusV,
  205. "acl_type": aclTypeV,
  206. "acl": aclV,
  207. "scheduler": validators.NewStringChoicesValidator("scheduler", api.LB_SCHEDULER_TYPES),
  208. "egress_mbps": validators.NewRangeValidator("egress_mbps", api.LB_MbpsMin, api.LB_MbpsMax),
  209. "client_request_timeout": validators.NewRangeValidator("client_request_timeout", 0, 600),
  210. "client_idle_timeout": validators.NewRangeValidator("client_idle_timeout", 0, 600),
  211. "backend_connect_timeout": validators.NewRangeValidator("backend_connect_timeout", 0, 180),
  212. "backend_idle_timeout": validators.NewRangeValidator("backend_idle_timeout", 0, 600),
  213. "sticky_session": validators.NewStringChoicesValidator("sticky_session", api.LB_BOOL_VALUES),
  214. "sticky_session_type": validators.NewStringChoicesValidator("sticky_session_type", api.LB_STICKY_SESSION_TYPES),
  215. "sticky_session_cookie": validators.NewRegexpValidator("sticky_session_cookie", regexp.MustCompile(`\w+`)),
  216. "sticky_session_cookie_timeout": validators.NewNonNegativeValidator("sticky_session_cookie_timeout"),
  217. "health_check": validators.NewStringChoicesValidator("health_check", api.LB_BOOL_VALUES),
  218. "health_check_type": models.LoadbalancerListenerManager.CheckTypeV(lblis.ListenerType),
  219. "health_check_domain": validators.NewDomainNameValidator("health_check_domain").AllowEmpty(true),
  220. "health_check_path": validators.NewURLPathValidator("health_check_path"),
  221. "health_check_http_code": validators.NewStringMultiChoicesValidator("health_check_http_code", api.LB_HEALTH_CHECK_HTTP_CODES).Sep(","),
  222. "health_check_rise": validators.NewRangeValidator("health_check_rise", 1, 1000),
  223. "health_check_fall": validators.NewRangeValidator("health_check_fall", 1, 1000),
  224. "health_check_timeout": validators.NewRangeValidator("health_check_timeout", 1, 300),
  225. "health_check_interval": validators.NewRangeValidator("health_check_interval", 1, 1000),
  226. "x_forwarded_for": validators.NewBoolValidator("x_forwarded_for"),
  227. "gzip": validators.NewBoolValidator("gzip"),
  228. "http_request_rate": validators.NewNonNegativeValidator("http_request_rate"),
  229. "http_request_rate_per_src": validators.NewNonNegativeValidator("http_request_rate_per_src"),
  230. "certificate": certV,
  231. "tls_cipher_policy": tlsCipherPolicyV,
  232. "enable_http2": validators.NewBoolValidator("enable_http2"),
  233. "redirect": redirectV,
  234. "redirect_code": redirectCodeV,
  235. "redirect_scheme": redirectSchemeV,
  236. "redirect_host": redirectHostV.AllowEmpty(true),
  237. "redirect_path": redirectPathV.AllowEmpty(true),
  238. }
  239. if err := RunValidators(keyV, data, true); err != nil {
  240. return nil, err
  241. }
  242. var (
  243. redirectType = redirectV.Value
  244. listenerType = lblis.ListenerType
  245. )
  246. if redirectType != api.LB_REDIRECT_OFF {
  247. if redirectType == api.LB_REDIRECT_RAW {
  248. scheme, host, path := redirectSchemeV.Value, redirectHostV.Value, redirectPathV.Value
  249. if (scheme == "" || scheme == listenerType) && host == "" && path == "" {
  250. return nil, httperrors.NewInputParameterError("redirect must have at least one of scheme, host, path changed")
  251. }
  252. }
  253. }
  254. // NOTE: it's okay we turn off redirect
  255. //
  256. // - scheduler have default value on creation
  257. // - backend_group_id is allowed to have unset value for http, https listener
  258. if err := models.LoadbalancerListenerManager.ValidateAcl(aclStatusV, aclTypeV, aclV, data, lblis.GetProviderName()); err != nil {
  259. return nil, err
  260. }
  261. {
  262. if backendGroup == nil {
  263. if lblis.ListenerType != api.LB_LISTENER_TYPE_HTTP &&
  264. lblis.ListenerType != api.LB_LISTENER_TYPE_HTTPS {
  265. return nil, httperrors.NewInputParameterError("non http listener must have backend group set")
  266. }
  267. } else if lbbg, ok := backendGroup.(*models.SLoadbalancerBackendGroup); ok && lbbg.LoadbalancerId != lblis.LoadbalancerId {
  268. return nil, httperrors.NewInputParameterError("backend group %s(%s) belongs to loadbalancer %s instead of %s",
  269. lbbg.Name, lbbg.Id, lbbg.LoadbalancerId, lblis.LoadbalancerId)
  270. }
  271. }
  272. */
  273. return input, nil
  274. }
  275. func (self *SKVMRegionDriver) RequestCreateLoadbalancerInstance(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, input *api.LoadbalancerCreateInput, task taskman.ITask) error {
  276. taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
  277. _, err := db.Update(lb, func() error {
  278. // TODO support use reserved ip address
  279. req := &models.SLoadbalancerNetworkRequestData{
  280. Loadbalancer: lb,
  281. NetworkId: lb.NetworkId,
  282. Address: lb.Address,
  283. }
  284. // NOTE the small window when agents can see the ephemeral address
  285. ln, err := models.LoadbalancernetworkManager.NewLoadbalancerNetwork(ctx, userCred, req)
  286. if err != nil {
  287. log.Errorf("allocating loadbalancer network failed: %v, req: %#v", err, req)
  288. lb.Address = ""
  289. } else {
  290. lb.Address = ln.IpAddr
  291. }
  292. return nil
  293. })
  294. if err != nil {
  295. return nil, errors.Wrapf(err, "db.Update")
  296. }
  297. // bind eip
  298. eipAddr := ""
  299. if input.EipBw > 0 && len(input.EipId) == 0 {
  300. // create eip first
  301. eipPendingUsage := &models.SRegionQuota{Eip: 1}
  302. eipPendingUsage.SetKeys(lb.GetQuotaKeys())
  303. eip, err := models.ElasticipManager.NewEipForVMOnHost(ctx, userCred, &models.NewEipForVMOnHostArgs{
  304. Bandwidth: input.EipBw,
  305. BgpType: input.EipBgpType,
  306. ChargeType: input.EipChargeType,
  307. AutoDellocate: input.EipAutoDellocate,
  308. Loadbalancer: lb,
  309. PendingUsage: eipPendingUsage,
  310. })
  311. if err != nil {
  312. log.Errorf("NewEipForVMOnHost fail %s", err)
  313. quotas.CancelPendingUsage(ctx, userCred, eipPendingUsage, eipPendingUsage, false)
  314. } else {
  315. eipAddr = eip.IpAddr
  316. opts := api.ElasticipAssociateInput{
  317. InstanceId: lb.Id,
  318. InstanceExternalId: lb.ExternalId,
  319. InstanceType: api.EIP_ASSOCIATE_TYPE_LOADBALANCER,
  320. }
  321. err = eip.AllocateAndAssociateInstance(ctx, userCred, lb, opts, "")
  322. if err != nil {
  323. return nil, errors.Wrap(err, "AllocateAndAssociateInstance")
  324. }
  325. }
  326. } else if len(input.EipId) > 0 {
  327. _eip, err := models.ElasticipManager.FetchById(input.EipId)
  328. if err != nil {
  329. return nil, errors.Wrapf(err, "ElasticipManager.FetchById(%s)", input.EipId)
  330. }
  331. eip := _eip.(*models.SElasticip)
  332. err = eip.AssociateLoadbalancer(ctx, userCred, lb)
  333. if err != nil {
  334. return nil, errors.Wrapf(err, "eip.AssociateLoadbalancer")
  335. }
  336. eipAddr = eip.IpAddr
  337. }
  338. if len(eipAddr) > 0 {
  339. _, err = db.Update(lb, func() error {
  340. lb.Address = eipAddr
  341. lb.AddressType = api.LB_ADDR_TYPE_INTERNET
  342. return nil
  343. })
  344. if err != nil {
  345. return nil, errors.Wrap(err, "set loadbalancer address")
  346. }
  347. }
  348. return nil, nil
  349. })
  350. return nil
  351. }
  352. func (self *SKVMRegionDriver) RequestStartLoadbalancer(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, task taskman.ITask) error {
  353. return task.ScheduleRun(nil)
  354. }
  355. func (self *SKVMRegionDriver) RequestStopLoadbalancer(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, task taskman.ITask) error {
  356. return task.ScheduleRun(nil)
  357. }
  358. func (self *SKVMRegionDriver) RequestSyncstatusLoadbalancer(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, task taskman.ITask) error {
  359. originStatus, _ := task.GetParams().GetString("origin_status")
  360. if utils.IsInStringArray(originStatus, []string{api.LB_STATUS_ENABLED, api.LB_STATUS_DISABLED}) {
  361. lb.SetStatus(ctx, userCred, originStatus, "")
  362. } else {
  363. lb.SetStatus(ctx, userCred, api.LB_STATUS_ENABLED, "")
  364. }
  365. return task.ScheduleRun(nil)
  366. }
  367. func (self *SKVMRegionDriver) RequestDeleteLoadbalancer(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, task taskman.ITask) error {
  368. return task.ScheduleRun(nil)
  369. }
  370. func (self *SKVMRegionDriver) RequestCreateLoadbalancerAcl(ctx context.Context, userCred mcclient.TokenCredential, lbacl *models.SLoadbalancerAcl, task taskman.ITask) error {
  371. return task.ScheduleRun(nil)
  372. }
  373. func (self *SKVMRegionDriver) RequestUpdateLoadbalancerAcl(ctx context.Context, userCred mcclient.TokenCredential, lbacl *models.SLoadbalancerAcl, task taskman.ITask) error {
  374. return task.ScheduleRun(nil)
  375. }
  376. func (self *SKVMRegionDriver) RequestLoadbalancerAclSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, lbacl *models.SLoadbalancerAcl, task taskman.ITask) error {
  377. lbacl.SetStatus(ctx, userCred, apis.STATUS_AVAILABLE, "")
  378. return task.ScheduleRun(nil)
  379. }
  380. func (self *SKVMRegionDriver) RequestDeleteLoadbalancerAcl(ctx context.Context, userCred mcclient.TokenCredential, lbacl *models.SLoadbalancerAcl, task taskman.ITask) error {
  381. return task.ScheduleRun(nil)
  382. }
  383. func (self *SKVMRegionDriver) RequestCreateLoadbalancerCertificate(ctx context.Context, userCred mcclient.TokenCredential, lbcert *models.SLoadbalancerCertificate, task taskman.ITask) error {
  384. return task.ScheduleRun(nil)
  385. }
  386. func (self *SKVMRegionDriver) RequestDeleteLoadbalancerCertificate(ctx context.Context, userCred mcclient.TokenCredential, lbcert *models.SLoadbalancerCertificate, task taskman.ITask) error {
  387. return task.ScheduleRun(nil)
  388. }
  389. func (self *SKVMRegionDriver) RequestLoadbalancerCertificateSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, lbcert *models.SLoadbalancerCertificate, task taskman.ITask) error {
  390. lbcert.SetStatus(ctx, userCred, apis.STATUS_AVAILABLE, "")
  391. return task.ScheduleRun(nil)
  392. }
  393. func (self *SKVMRegionDriver) RequestCreateLoadbalancerBackendGroup(ctx context.Context, userCred mcclient.TokenCredential, lbbg *models.SLoadbalancerBackendGroup, task taskman.ITask) error {
  394. return task.ScheduleRun(nil)
  395. }
  396. func (self *SKVMRegionDriver) RequestDeleteLoadbalancerBackendGroup(ctx context.Context, userCred mcclient.TokenCredential, lbbg *models.SLoadbalancerBackendGroup, task taskman.ITask) error {
  397. task.ScheduleRun(nil)
  398. return nil
  399. }
  400. func (self *SKVMRegionDriver) RequestCreateLoadbalancerBackend(ctx context.Context, userCred mcclient.TokenCredential, lbb *models.SLoadbalancerBackend, task taskman.ITask) error {
  401. task.ScheduleRun(nil)
  402. return nil
  403. }
  404. func (self *SKVMRegionDriver) GetBackendStatusForAdd() []string {
  405. return []string{api.VM_RUNNING, api.VM_READY}
  406. }
  407. func (self *SKVMRegionDriver) RequestDeleteLoadbalancerBackend(ctx context.Context, userCred mcclient.TokenCredential, lbb *models.SLoadbalancerBackend, task taskman.ITask) error {
  408. task.ScheduleRun(nil)
  409. return nil
  410. }
  411. func (self *SKVMRegionDriver) RequestSyncLoadbalancerBackend(ctx context.Context, userCred mcclient.TokenCredential, lbb *models.SLoadbalancerBackend, task taskman.ITask) error {
  412. task.ScheduleRun(nil)
  413. return nil
  414. }
  415. func (self *SKVMRegionDriver) RequestCreateLoadbalancerListener(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, task taskman.ITask) error {
  416. task.ScheduleRun(nil)
  417. return nil
  418. }
  419. func (self *SKVMRegionDriver) RequestDeleteLoadbalancerListener(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, task taskman.ITask) error {
  420. return task.ScheduleRun(nil)
  421. }
  422. func (self *SKVMRegionDriver) RequestStartLoadbalancerListener(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, task taskman.ITask) error {
  423. task.ScheduleRun(nil)
  424. return nil
  425. }
  426. func (self *SKVMRegionDriver) RequestStopLoadbalancerListener(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, task taskman.ITask) error {
  427. task.ScheduleRun(nil)
  428. return nil
  429. }
  430. func (self *SKVMRegionDriver) RequestSyncstatusLoadbalancerListener(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, task taskman.ITask) error {
  431. originStatus, _ := task.GetParams().GetString("origin_status")
  432. if utils.IsInStringArray(originStatus, []string{api.LB_STATUS_ENABLED, api.LB_STATUS_DISABLED}) {
  433. lblis.SetStatus(ctx, userCred, originStatus, "")
  434. } else {
  435. lblis.SetStatus(ctx, userCred, api.LB_STATUS_ENABLED, "")
  436. }
  437. task.ScheduleRun(nil)
  438. return nil
  439. }
  440. func (self *SKVMRegionDriver) RequestSyncLoadbalancerListener(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, input *api.LoadbalancerListenerUpdateInput, task taskman.ITask) error {
  441. task.ScheduleRun(nil)
  442. return nil
  443. }
  444. func (self *SKVMRegionDriver) RequestCreateLoadbalancerListenerRule(ctx context.Context, userCred mcclient.TokenCredential, lbr *models.SLoadbalancerListenerRule, task taskman.ITask) error {
  445. task.ScheduleRun(nil)
  446. return nil
  447. }
  448. func (self *SKVMRegionDriver) RequestDeleteLoadbalancerListenerRule(ctx context.Context, userCred mcclient.TokenCredential, lbr *models.SLoadbalancerListenerRule, task taskman.ITask) error {
  449. task.ScheduleRun(nil)
  450. return nil
  451. }
  452. func (self *SKVMRegionDriver) ValidateCreateVpcData(ctx context.Context, userCred mcclient.TokenCredential, input api.VpcCreateInput) (api.VpcCreateInput, error) {
  453. if len(input.CidrBlock) > 0 && !utils.IsInStringArray(input.CidrBlock, []string{"192.168.0.0/16", "10.0.0.0/8", "172.16.0.0/12"}) {
  454. return input, httperrors.NewInputParameterError("Invalid cidr_block, want 192.168.0.0/16|10.0.0.0/8|172.16.0.0/12, got %s", input.CidrBlock)
  455. }
  456. if len(input.CidrBlock6) > 0 {
  457. input.CidrBlock6 = strings.ToLower(input.CidrBlock6)
  458. if !strings.HasPrefix(input.CidrBlock6, "fd") {
  459. return input, httperrors.NewInputParameterError("Invalid ipv6 cidr_block, %s outside of IPv6 private unicast address range fd00::/8", input.CidrBlock6)
  460. }
  461. }
  462. return input, nil
  463. }
  464. func (self *SKVMRegionDriver) RequestDeleteVpc(ctx context.Context, userCred mcclient.TokenCredential, region *models.SCloudregion, vpc *models.SVpc, task taskman.ITask) error {
  465. task.ScheduleRun(nil)
  466. return nil
  467. }
  468. func (self *SKVMRegionDriver) GetEipDefaultChargeType() billing_api.TNetChargeType {
  469. return billing_api.NET_CHARGE_TYPE_BY_BANDWIDTH
  470. }
  471. func (self *SKVMRegionDriver) ValidateEipChargeType(chargeType billing_api.TNetChargeType) error {
  472. if chargeType != billing_api.NET_CHARGE_TYPE_BY_BANDWIDTH {
  473. return httperrors.NewInputParameterError("%s only supports eip charge type %q",
  474. self.GetProvider(), billing_api.NET_CHARGE_TYPE_BY_BANDWIDTH)
  475. }
  476. return nil
  477. }
  478. func (self *SKVMRegionDriver) ValidateCreateEipData(ctx context.Context, userCred mcclient.TokenCredential, input *api.SElasticipCreateInput) error {
  479. if err := self.ValidateEipChargeType(input.ChargeType); err != nil {
  480. return err
  481. }
  482. var network *models.SNetwork
  483. if input.NetworkId != "" {
  484. _network, err := models.NetworkManager.FetchByIdOrName(ctx, userCred, input.NetworkId)
  485. if err != nil {
  486. if err == sql.ErrNoRows {
  487. return httperrors.NewResourceNotFoundError2("network", input.NetworkId)
  488. }
  489. return httperrors.NewGeneralError(err)
  490. }
  491. network = _network.(*models.SNetwork)
  492. input.BgpType = network.BgpType
  493. } else {
  494. q := models.NetworkManager.Query().
  495. Equals("server_type", api.NETWORK_TYPE_EIP).
  496. Equals("bgp_type", input.BgpType)
  497. var nets []models.SNetwork
  498. if err := db.FetchModelObjects(models.NetworkManager, q, &nets); err != nil {
  499. return err
  500. }
  501. eipNets := make([]models.SEipNetwork, 0)
  502. for i := range nets {
  503. net := &nets[i]
  504. cnt, _ := net.GetFreeAddressCount()
  505. if cnt > 0 {
  506. eipNets = append(eipNets, models.NewEipNetwork(net, userCred, userCred, cnt))
  507. }
  508. }
  509. if len(eipNets) == 0 {
  510. return httperrors.NewNotFoundError("no available eip network")
  511. }
  512. // prefer networks with identical project, domain, more free address, Id
  513. sort.Sort(models.SEipNetworks(eipNets))
  514. log.Debugf("eipnets: %s", jsonutils.Marshal(eipNets))
  515. network = eipNets[0].GetNetwork()
  516. input.NetworkId = network.Id
  517. }
  518. if network.ServerType != api.NETWORK_TYPE_EIP {
  519. return httperrors.NewInputParameterError("bad network type %q, want %q", network.ServerType, api.NETWORK_TYPE_EIP)
  520. }
  521. input.NetworkId = network.Id
  522. if len(input.IpAddr) > 0 {
  523. if !network.Contains(input.IpAddr) {
  524. return httperrors.NewInputParameterError("candidate %s out of range", input.IpAddr)
  525. }
  526. addrTable := network.GetUsedAddresses(ctx)
  527. if _, ok := addrTable[input.IpAddr]; ok {
  528. return httperrors.NewInputParameterError("requested ip %s is occupied!", input.IpAddr)
  529. }
  530. }
  531. vpc, _ := network.GetVpc()
  532. if vpc == nil {
  533. return httperrors.NewInputParameterError("failed to found vpc for network %s(%s)", network.Name, network.Id)
  534. }
  535. region, err := vpc.GetRegion()
  536. if err != nil {
  537. return err
  538. }
  539. if region.Id != input.CloudregionId {
  540. return httperrors.NewUnsupportOperationError("network %s(%s) does not belong to %s", network.Name, network.Id, self.GetProvider())
  541. }
  542. return nil
  543. }
  544. func (self *SKVMRegionDriver) ValidateSnapshotDelete(ctx context.Context, snapshot *models.SSnapshot) error {
  545. storage := snapshot.GetStorage()
  546. if storage == nil {
  547. return httperrors.NewInternalServerError("Kvm snapshot missing storage ??")
  548. }
  549. return models.GetStorageDriver(storage.StorageType).ValidateSnapshotDelete(ctx, snapshot)
  550. }
  551. func (self *SKVMRegionDriver) RequestDeleteSnapshot(ctx context.Context, snapshot *models.SSnapshot, task taskman.ITask) error {
  552. storage := snapshot.GetStorage()
  553. if storage == nil {
  554. return httperrors.NewInternalServerError("Kvm snapshot missing storage ??")
  555. }
  556. return models.GetStorageDriver(storage.StorageType).RequestDeleteSnapshot(ctx, snapshot, task)
  557. }
  558. func (self *SKVMRegionDriver) RequestDeleteInstanceSnapshot(ctx context.Context, isp *models.SInstanceSnapshot, task taskman.ITask) error {
  559. snapshots, err := isp.GetSnapshots()
  560. if err != nil {
  561. return err
  562. }
  563. if len(snapshots) == 0 {
  564. task.SetStage("OnInstanceSnapshotDelete", nil)
  565. if isp.WithMemory && isp.MemoryFileHostId != "" && isp.MemoryFilePath != "" {
  566. // request delete memory snapshot
  567. host := models.HostManager.FetchHostById(isp.MemoryFileHostId)
  568. if host == nil {
  569. return errors.Errorf("Not found host by %q", isp.MemoryFileHostId)
  570. }
  571. header := task.GetTaskRequestHeader()
  572. url := fmt.Sprintf("%s/servers/memory-snapshot", host.ManagerUri)
  573. if _, _, err := httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "DELETE", url, header, jsonutils.Marshal(&hostapi.GuestMemorySnapshotDeleteRequest{
  574. InstanceSnapshotId: isp.GetId(),
  575. Path: isp.MemoryFilePath,
  576. }), false); err != nil {
  577. return err
  578. }
  579. } else {
  580. taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
  581. return nil, nil
  582. })
  583. }
  584. return nil
  585. }
  586. params := jsonutils.NewDict()
  587. taskParams := task.GetParams()
  588. var deleteSnapshotTotalCnt int64 = 1
  589. if taskParams.Contains("snapshot_total_count") {
  590. deleteSnapshotTotalCnt, _ = taskParams.Int("snapshot_total_count")
  591. }
  592. deletedSnapshotCnt := deleteSnapshotTotalCnt - int64(len(snapshots))
  593. params.Set("del_snapshot_id", jsonutils.NewString(snapshots[0].Id))
  594. task.SetStage("OnKvmSnapshotDelete", params)
  595. err = snapshots[0].StartSnapshotDeleteTask(ctx, task.GetUserCred(), false, task.GetTaskId(), int(deleteSnapshotTotalCnt), int(deletedSnapshotCnt))
  596. if err != nil {
  597. return err
  598. }
  599. return nil
  600. }
  601. func (self *SKVMRegionDriver) RequestDeleteInstanceBackup(ctx context.Context, ib *models.SInstanceBackup, task taskman.ITask) error {
  602. backups, err := ib.GetBackups()
  603. if err != nil {
  604. return err
  605. }
  606. if len(backups) == 0 {
  607. task.SetStage("OnInstanceBackupDelete", nil)
  608. taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
  609. return nil, nil
  610. })
  611. return nil
  612. }
  613. params := jsonutils.NewDict()
  614. params.Set("del_backup_id", jsonutils.NewString(backups[0].Id))
  615. task.SetStage("OnKvmDiskBackupDelete", params)
  616. forceDelete := jsonutils.QueryBoolean(task.GetParams(), "force_delete", false)
  617. err = backups[0].StartBackupDeleteTask(ctx, task.GetUserCred(), task.GetTaskId(), forceDelete)
  618. if err != nil {
  619. return err
  620. }
  621. return nil
  622. }
  623. func (self *SKVMRegionDriver) RequestResetToInstanceSnapshot(ctx context.Context, guest *models.SGuest, isp *models.SInstanceSnapshot, task taskman.ITask, params *jsonutils.JSONDict) error {
  624. jIsps, err := isp.GetInstanceSnapshotJointsByOrder(guest)
  625. if err != nil {
  626. return errors.Wrap(err, "GetInstanceSnapshotJointsByOrder")
  627. }
  628. diskIndexI64, err := params.Int("disk_index")
  629. if err != nil {
  630. return errors.Wrap(err, "get 'disk_index' from params")
  631. }
  632. diskIndex := int(diskIndexI64)
  633. if diskIndex >= len(jIsps) {
  634. task.SetStage("OnInstanceSnapshotReset", nil)
  635. withMem := jsonutils.QueryBoolean(params, "with_memory", false)
  636. if isp.WithMemory && withMem {
  637. // reset do memory snapshot
  638. host, err := guest.GetHost()
  639. if err != nil {
  640. return err
  641. }
  642. header := task.GetTaskRequestHeader()
  643. url := fmt.Sprintf("%s/servers/%s/memory-snapshot-reset", host.ManagerUri, guest.GetId())
  644. if _, _, err := httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, header, jsonutils.Marshal(&hostapi.GuestMemorySnapshotResetRequest{
  645. InstanceSnapshotId: isp.GetId(),
  646. Path: isp.MemoryFilePath,
  647. Checksum: isp.MemoryFileChecksum,
  648. }), false); err != nil {
  649. return err
  650. }
  651. } else {
  652. taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
  653. return nil, nil
  654. })
  655. }
  656. return nil
  657. }
  658. isj := jIsps[diskIndex]
  659. params = jsonutils.NewDict()
  660. params.Set("disk_index", jsonutils.NewInt(int64(diskIndex)))
  661. task.SetStage("OnKvmDiskReset", params)
  662. disk, err := isj.GetSnapshotDisk()
  663. if err != nil {
  664. return errors.Wrapf(err, "Get %d snapshot disk", diskIndex)
  665. }
  666. err = disk.StartResetDisk(ctx, task.GetUserCred(), isj.SnapshotId, false, guest, task.GetTaskId())
  667. if err != nil {
  668. return errors.Wrap(err, "StartResetDisk")
  669. }
  670. return nil
  671. }
  672. func (self *SKVMRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SnapshotCreateInput) error {
  673. _, err := storage.GetMasterHost()
  674. if err != nil {
  675. return errors.Wrapf(err, "storage.GetMasterHost")
  676. }
  677. return models.GetStorageDriver(storage.StorageType).ValidateCreateSnapshotData(ctx, userCred, disk, input)
  678. }
  679. func (self *SKVMRegionDriver) RequestCreateSnapshot(ctx context.Context, snapshot *models.SSnapshot, task taskman.ITask) error {
  680. storage := snapshot.GetStorage()
  681. if storage == nil {
  682. return httperrors.NewInternalServerError("Kvm snapshot missing storage ??")
  683. }
  684. return models.GetStorageDriver(storage.StorageType).RequestCreateSnapshot(ctx, snapshot, task)
  685. }
  686. func (self *SKVMRegionDriver) RequestCreateInstanceSnapshot(ctx context.Context, guest *models.SGuest, isp *models.SInstanceSnapshot, task taskman.ITask, params *jsonutils.JSONDict) error {
  687. disks, _ := guest.GetGuestDisks()
  688. diskIndexI64, err := params.Int("disk_index")
  689. if err != nil {
  690. return errors.Wrap(err, "get 'disk_index' from params")
  691. }
  692. diskIndex := int(diskIndexI64)
  693. if diskIndex >= len(disks) {
  694. task.SetStage("OnInstanceSnapshot", nil)
  695. if isp.WithMemory {
  696. // request do memory snapshot
  697. host, err := guest.GetHost()
  698. if err != nil {
  699. return err
  700. }
  701. header := task.GetTaskRequestHeader()
  702. url := fmt.Sprintf("%s/servers/%s/memory-snapshot", host.ManagerUri, guest.GetId())
  703. if _, _, err := httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, header, jsonutils.Marshal(&hostapi.GuestMemorySnapshotRequest{
  704. InstanceSnapshotId: isp.GetId(),
  705. }), false); err != nil {
  706. return err
  707. }
  708. } else {
  709. taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
  710. return nil, nil
  711. })
  712. }
  713. return nil
  714. }
  715. snapshot, err := func() (*models.SSnapshot, error) {
  716. lockman.LockClass(ctx, models.SnapshotManager, "name")
  717. defer lockman.ReleaseClass(ctx, models.SnapshotManager, "name")
  718. snapshotName, err := db.GenerateName(ctx, models.SnapshotManager, task.GetUserCred(),
  719. fmt.Sprintf("%s-%s", isp.Name, randutil.String(8)))
  720. if err != nil {
  721. return nil, errors.Wrap(err, "Generate snapshot name")
  722. }
  723. return models.SnapshotManager.CreateSnapshot(
  724. ctx, task.GetUserCred(), api.SNAPSHOT_MANUAL, disks[diskIndex].DiskId,
  725. guest.Id, "", snapshotName, -1, false, "")
  726. }()
  727. if err != nil {
  728. return err
  729. }
  730. err = isp.InheritTo(ctx, task.GetUserCred(), snapshot)
  731. if err != nil {
  732. return errors.Wrapf(err, "unable to inherit from instance snapshot %s to snapshot %s", isp.GetId(), snapshot.GetId())
  733. }
  734. err = models.InstanceSnapshotJointManager.CreateJoint(ctx, isp.Id, snapshot.Id, int8(diskIndex))
  735. if err != nil {
  736. return err
  737. }
  738. params = jsonutils.NewDict()
  739. params.Set("disk_index", jsonutils.NewInt(int64(diskIndex)))
  740. params.Set(strconv.Itoa(diskIndex), jsonutils.NewString(snapshot.Id))
  741. task.SetStage("OnKvmDiskSnapshot", params)
  742. if err := snapshot.StartSnapshotCreateTask(ctx, task.GetUserCred(), nil, task.GetTaskId()); err != nil {
  743. return err
  744. }
  745. return nil
  746. }
  747. func (self *SKVMRegionDriver) SnapshotIsOutOfChain(disk *models.SDisk) bool {
  748. storage, _ := disk.GetStorage()
  749. return models.GetStorageDriver(storage.StorageType).SnapshotIsOutOfChain(disk)
  750. }
  751. func (self *SKVMRegionDriver) GetDiskResetParams(snapshot *models.SSnapshot) *jsonutils.JSONDict {
  752. params := jsonutils.NewDict()
  753. params.Set("snapshot_id", jsonutils.NewString(snapshot.Id))
  754. params.Set("out_of_chain", jsonutils.NewBool(snapshot.OutOfChain))
  755. params.Set("location", jsonutils.NewString(snapshot.Location))
  756. if len(snapshot.BackingDiskId) > 0 {
  757. params.Set("backing_disk_id", jsonutils.NewString(snapshot.BackingDiskId))
  758. }
  759. return params
  760. }
  761. func (self *SKVMRegionDriver) OnDiskReset(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, snapshot *models.SSnapshot, data jsonutils.JSONObject) error {
  762. if disk.DiskSize != snapshot.VirtualSize {
  763. _, err := db.Update(disk, func() error {
  764. disk.DiskSize = snapshot.VirtualSize
  765. return nil
  766. })
  767. if err != nil {
  768. return err
  769. }
  770. }
  771. storage, _ := disk.GetStorage()
  772. return models.GetStorageDriver(storage.StorageType).OnDiskReset(ctx, userCred, disk, snapshot, data)
  773. }
  774. func (self *SKVMRegionDriver) OnSnapshotDelete(ctx context.Context, snapshot *models.SSnapshot, task taskman.ITask, data jsonutils.JSONObject) error {
  775. task.SetStage("OnKvmSnapshotDelete", nil)
  776. task.ScheduleRun(data)
  777. return nil
  778. }
  779. func (self *SKVMRegionDriver) RequestSyncDiskStatus(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, task taskman.ITask) error {
  780. taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
  781. storage, err := disk.GetStorage()
  782. if err != nil {
  783. return nil, errors.Wrapf(err, "disk.GetStorage")
  784. }
  785. host, err := storage.GetMasterHost()
  786. if err != nil {
  787. return nil, errors.Wrapf(err, "storage.GetMasterHost")
  788. }
  789. header := task.GetTaskRequestHeader()
  790. url := fmt.Sprintf("%s/disks/%s/%s/status", host.ManagerUri, storage.Id, disk.Id)
  791. _, res, err := httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "GET", url, header, nil, false)
  792. if err != nil {
  793. return nil, err
  794. }
  795. var diskStatus string
  796. originStatus, _ := task.GetParams().GetString("origin_status")
  797. status, _ := res.GetString("status")
  798. if status == api.DISK_EXIST {
  799. if utils.IsInArray(originStatus, []string{
  800. api.DISK_UNKNOWN,
  801. api.DISK_REBUILD_FAILED,
  802. api.DISK_ATTACHING,
  803. api.DISK_DETACHING,
  804. }) {
  805. diskStatus = api.DISK_READY
  806. } else {
  807. diskStatus = originStatus
  808. }
  809. } else {
  810. diskStatus = api.DISK_UNKNOWN
  811. }
  812. return nil, disk.SetStatus(ctx, userCred, diskStatus, "sync status")
  813. })
  814. return nil
  815. }
  816. func (self *SKVMRegionDriver) RequestCreateInstanceBackup(ctx context.Context, guest *models.SGuest, ib *models.SInstanceBackup, task taskman.ITask, params *jsonutils.JSONDict) error {
  817. disks, _ := guest.GetGuestDisks()
  818. task.SetStage("OnKvmDisksSnapshot", params)
  819. for i := range disks {
  820. disk := disks[i]
  821. backup, err := func() (*models.SDiskBackup, error) {
  822. lockman.LockClass(ctx, models.DiskBackupManager, "name")
  823. defer lockman.ReleaseClass(ctx, models.DiskBackupManager, "name")
  824. diskBackupName, err := db.GenerateName(ctx, models.DiskBackupManager, task.GetUserCred(),
  825. fmt.Sprintf("%s-%s", ib.Name, randutil.String(8)))
  826. if err != nil {
  827. return nil, errors.Wrap(err, "Generate diskbackup name")
  828. }
  829. return models.DiskBackupManager.CreateBackup(ctx, task.GetUserCred(), disk.DiskId, ib.BackupStorageId, diskBackupName)
  830. }()
  831. if err != nil {
  832. return err
  833. }
  834. err = ib.InheritTo(ctx, task.GetUserCred(), backup)
  835. if err != nil {
  836. return errors.Wrapf(err, "unable to inherit from instance backup %s to backup %s", ib.GetId(), backup.GetId())
  837. }
  838. err = models.InstanceBackupJointManager.CreateJoint(ctx, ib.Id, backup.Id, int8(i))
  839. if err != nil {
  840. return err
  841. }
  842. taskParams := jsonutils.NewDict()
  843. taskParams.Set("only_snapshot", jsonutils.JSONTrue)
  844. if err := backup.StartBackupCreateTask(ctx, task.GetUserCred(), taskParams, task.GetTaskId()); err != nil {
  845. return err
  846. }
  847. }
  848. return nil
  849. }
  850. func (self *SKVMRegionDriver) RequestPackInstanceBackup(ctx context.Context, ib *models.SInstanceBackup, task taskman.ITask, packageName string) error {
  851. backupStorage, err := ib.GetBackupStorage()
  852. if err != nil {
  853. return errors.Wrap(err, "unable to get backupStorage")
  854. }
  855. backups, err := ib.GetBackups()
  856. if err != nil {
  857. return errors.Wrap(err, "unable to get backups")
  858. }
  859. host, err := models.HostManager.GetEnabledKvmHostForDiskBackup(&backups[0])
  860. if err != nil {
  861. return errors.Wrap(err, "GetEnabledKvmHostForDiskBackup")
  862. }
  863. backupIds := make([]string, len(backups))
  864. for i := range backupIds {
  865. backupIds[i] = backups[i].GetId()
  866. }
  867. metadata, err := ib.PackMetadata(ctx, task.GetUserCred())
  868. if err != nil {
  869. return errors.Wrap(err, "unable to PackMetadata")
  870. }
  871. url := fmt.Sprintf("%s/storages/pack-instance-backup", host.ManagerUri)
  872. body := jsonutils.NewDict()
  873. body.Set("package_name", jsonutils.NewString(packageName))
  874. body.Set("backup_storage_id", jsonutils.NewString(backupStorage.GetId()))
  875. accessInfo, err := backupStorage.GetAccessInfo()
  876. if err != nil {
  877. return errors.Wrap(err, "GetAccessInfo")
  878. }
  879. body.Set("backup_storage_access_info", jsonutils.Marshal(accessInfo))
  880. body.Set("backup_ids", jsonutils.Marshal(backupIds))
  881. body.Set("metadata", jsonutils.Marshal(metadata))
  882. header := task.GetTaskRequestHeader()
  883. _, _, err = httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, header, body, false)
  884. if err != nil {
  885. return errors.Wrap(err, "unable to pack instancebackup")
  886. }
  887. return nil
  888. }
  889. func (self *SKVMRegionDriver) RequestUnpackInstanceBackup(ctx context.Context, ib *models.SInstanceBackup, task taskman.ITask, packageName string, metadataOnly bool) error {
  890. log.Infof("RequestUnpackInstanceBackup")
  891. backupStorage, err := ib.GetBackupStorage()
  892. if err != nil {
  893. return errors.Wrap(err, "unable to get backupStorage")
  894. }
  895. host, err := models.HostManager.GetEnabledKvmHostForBackupStorage(backupStorage)
  896. if err != nil {
  897. return errors.Wrap(err, "unable to GetEnabledKvmHost")
  898. }
  899. url := fmt.Sprintf("%s/storages/unpack-instance-backup", host.ManagerUri)
  900. log.Infof("url: %s", url)
  901. body := jsonutils.NewDict()
  902. body.Set("package_name", jsonutils.NewString(packageName))
  903. body.Set("backup_storage_id", jsonutils.NewString(backupStorage.GetId()))
  904. accessInfo, err := backupStorage.GetAccessInfo()
  905. if err != nil {
  906. return errors.Wrap(err, "GetAccessInfo")
  907. }
  908. body.Set("backup_storage_access_info", jsonutils.Marshal(accessInfo))
  909. if metadataOnly {
  910. body.Set("metadata_only", jsonutils.JSONTrue)
  911. }
  912. header := task.GetTaskRequestHeader()
  913. _, _, err = httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, header, body, false)
  914. if err != nil {
  915. return errors.Wrap(err, "unable to pack instancebackup")
  916. }
  917. return nil
  918. }
  919. func (self *SKVMRegionDriver) RequestSyncBackupStorageStatus(ctx context.Context, userCred mcclient.TokenCredential, bs *models.SBackupStorage, task taskman.ITask) error {
  920. taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
  921. host, err := models.HostManager.GetEnabledKvmHostForBackupStorage(bs)
  922. if err != nil {
  923. return nil, errors.Wrap(err, "GetEnabledKvmHostForBackupStorage")
  924. }
  925. url := fmt.Sprintf("%s/storages/sync-backup-storage", host.ManagerUri)
  926. body := jsonutils.NewDict()
  927. body.Set("backup_storage_id", jsonutils.NewString(bs.GetId()))
  928. accessInfo, err := bs.GetAccessInfo()
  929. if err != nil {
  930. return nil, errors.Wrap(err, "GetAccessInfo")
  931. }
  932. body.Set("backup_storage_access_info", jsonutils.Marshal(accessInfo))
  933. header := task.GetTaskRequestHeader()
  934. _, res, err := httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, header, body, false)
  935. if err != nil {
  936. return nil, err
  937. }
  938. status, _ := res.GetString("status")
  939. reason, _ := res.GetString("reason")
  940. return nil, bs.SetStatus(ctx, userCred, status, reason)
  941. })
  942. return nil
  943. }
  944. func (self *SKVMRegionDriver) RequestSyncInstanceBackupStatus(ctx context.Context, userCred mcclient.TokenCredential, ib *models.SInstanceBackup, task taskman.ITask) error {
  945. originStatus, _ := task.GetParams().GetString("origin_status")
  946. if utils.IsInStringArray(originStatus, []string{
  947. api.INSTANCE_BACKUP_STATUS_CREATING,
  948. api.INSTANCE_BACKUP_STATUS_DELETING,
  949. // api.INSTANCE_BACKUP_STATUS_RECOVERY,
  950. api.INSTANCE_BACKUP_STATUS_PACK,
  951. api.INSTANCE_BACKUP_STATUS_CREATING_FROM_PACKAGE,
  952. api.INSTANCE_BACKUP_STATUS_SAVING,
  953. api.INSTANCE_BACKUP_STATUS_SNAPSHOT,
  954. }) {
  955. err := ib.SetStatus(ctx, userCred, originStatus, "sync status")
  956. if err != nil {
  957. return err
  958. }
  959. task.SetStageComplete(ctx, nil)
  960. return nil
  961. }
  962. taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
  963. task.SetStage("OnKvmBackupSyncstatus", nil)
  964. backups, err := ib.GetBackups()
  965. if err != nil {
  966. return nil, errors.Wrap(err, "unable to get backups")
  967. }
  968. for i := range backups {
  969. params := jsonutils.NewDict()
  970. params.Add(jsonutils.NewString(backups[i].GetStatus()), "origin_status")
  971. task, err := taskman.TaskManager.NewTask(ctx, "DiskBackupSyncstatusTask", &backups[i], userCred, params, task.GetTaskId(), "", nil)
  972. if err != nil {
  973. return nil, err
  974. }
  975. task.ScheduleRun(nil)
  976. }
  977. return nil, nil
  978. })
  979. return nil
  980. }
  981. func (self *SKVMRegionDriver) RequestSyncDiskBackupStatus(ctx context.Context, userCred mcclient.TokenCredential, backup *models.SDiskBackup, task taskman.ITask) error {
  982. taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
  983. originStatus, _ := task.GetParams().GetString("origin_status")
  984. if utils.IsInStringArray(originStatus, []string{api.BACKUP_STATUS_CREATING, api.BACKUP_STATUS_SNAPSHOT, api.BACKUP_STATUS_SAVING, api.BACKUP_STATUS_CLEANUP_SNAPSHOT, api.BACKUP_STATUS_DELETING}) {
  985. return nil, backup.SetStatus(ctx, userCred, originStatus, "sync status")
  986. }
  987. backupStorage, err := backup.GetBackupStorage()
  988. if err != nil {
  989. return nil, errors.Wrap(err, "unable to get backupStorage")
  990. }
  991. /*storage, _ := backup.GetStorage()
  992. var host *models.SHost
  993. if storage != nil {
  994. host, _ = storage.GetMasterHost()
  995. }
  996. if host == nil {
  997. host, err = models.HostManager.GetEnabledKvmHost()
  998. if err != nil {
  999. return nil, errors.Wrap(err, "unable to GetEnabledKvmHost")
  1000. }
  1001. }*/
  1002. host, err := models.HostManager.GetEnabledKvmHostForDiskBackup(backup)
  1003. if err != nil {
  1004. return nil, errors.Wrap(err, "GetEnabledKvmHostForDiskBackup")
  1005. }
  1006. log.Infof("host: %s, ManagerUri: %s", host.GetId(), host.ManagerUri)
  1007. url := fmt.Sprintf("%s/storages/sync-backup", host.ManagerUri)
  1008. body := jsonutils.NewDict()
  1009. body.Set("backup_id", jsonutils.NewString(backup.GetId()))
  1010. body.Set("backup_storage_id", jsonutils.NewString(backupStorage.GetId()))
  1011. accessInfo, err := backupStorage.GetAccessInfo()
  1012. if err != nil {
  1013. return nil, errors.Wrap(err, "GetAccessInfo")
  1014. }
  1015. body.Set("backup_storage_access_info", jsonutils.Marshal(accessInfo))
  1016. header := task.GetTaskRequestHeader()
  1017. _, res, err := httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, header, body, false)
  1018. if err != nil {
  1019. return nil, err
  1020. }
  1021. var backupStatus string
  1022. status, _ := res.GetString("status")
  1023. if status == api.BACKUP_EXIST {
  1024. backupStatus = api.BACKUP_STATUS_READY
  1025. } else {
  1026. backupStatus = api.BACKUP_STATUS_UNKNOWN
  1027. }
  1028. return nil, backup.SetStatus(ctx, userCred, backupStatus, "sync status")
  1029. })
  1030. return nil
  1031. }
  1032. func (self *SKVMRegionDriver) RequestSyncSnapshotStatus(ctx context.Context, userCred mcclient.TokenCredential, snapshot *models.SSnapshot, task taskman.ITask) error {
  1033. taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
  1034. storage := snapshot.GetStorage()
  1035. host, err := storage.GetMasterHost()
  1036. if err != nil {
  1037. return nil, errors.Wrapf(err, "storage.GetMasterHost")
  1038. }
  1039. header := task.GetTaskRequestHeader()
  1040. url := fmt.Sprintf("%s/snapshots/%s/%s/%s/status", host.ManagerUri, storage.Id, snapshot.DiskId, snapshot.Id)
  1041. _, res, err := httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "GET", url, header, nil, false)
  1042. if err != nil {
  1043. return nil, err
  1044. }
  1045. var snapshotStatus string
  1046. originStatus, _ := task.GetParams().GetString("origin_status")
  1047. status, _ := res.GetString("status")
  1048. if status == api.SNAPSHOT_EXIST {
  1049. if originStatus == api.SNAPSHOT_UNKNOWN {
  1050. snapshotStatus = api.SNAPSHOT_READY
  1051. } else {
  1052. snapshotStatus = originStatus
  1053. }
  1054. } else {
  1055. snapshotStatus = api.SNAPSHOT_UNKNOWN
  1056. }
  1057. return nil, snapshot.SetStatus(ctx, userCred, snapshotStatus, "sync status")
  1058. })
  1059. return nil
  1060. }
  1061. func (self *SKVMRegionDriver) RequestAssociateEipForNAT(ctx context.Context, userCred mcclient.TokenCredential, nat *models.SNatGateway, eip *models.SElasticip, task taskman.ITask) error {
  1062. return errors.Wrapf(cloudprovider.ErrNotSupported, "RequestAssociateEipForNAT")
  1063. }
  1064. func (self *SKVMRegionDriver) ValidateCacheSecgroup(ctx context.Context, userCred mcclient.TokenCredential, secgroup *models.SSecurityGroup, vpc *models.SVpc, classic bool) error {
  1065. return errors.Wrap(httperrors.ErrNotSupported, "No need to cache secgroup for onecloud region")
  1066. }
  1067. func (self *SKVMRegionDriver) ValidateCreateElasticcacheData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, input *api.ElasticcacheCreateInput) (*api.ElasticcacheCreateInput, error) {
  1068. return input, httperrors.NewNotSupportedError("Not support create elasticcache")
  1069. }
  1070. func (self *SKVMRegionDriver) RequestRestartElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *models.SElasticcache, task taskman.ITask) error {
  1071. return nil
  1072. }
  1073. func (self *SKVMRegionDriver) RequestSyncElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *models.SElasticcache, task taskman.ITask) error {
  1074. return nil
  1075. }
  1076. func (self *SKVMRegionDriver) RequestDeleteElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *models.SElasticcache, task taskman.ITask) error {
  1077. return nil
  1078. }
  1079. func (self *SKVMRegionDriver) RequestChangeElasticcacheSpec(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error {
  1080. return nil
  1081. }
  1082. func (self *SKVMRegionDriver) RequestSetElasticcacheMaintainTime(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error {
  1083. return nil
  1084. }
  1085. func (self *SKVMRegionDriver) RequestElasticcacheChangeSpec(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *models.SElasticcache, task taskman.ITask) error {
  1086. return nil
  1087. }
  1088. func (self *SKVMRegionDriver) RequestUpdateElasticcacheAuthMode(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *models.SElasticcache, task taskman.ITask) error {
  1089. return nil
  1090. }
  1091. func (self *SKVMRegionDriver) RequestUpdateElasticcacheSecgroups(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error {
  1092. return nil
  1093. }
  1094. func (self *SKVMRegionDriver) RequestElasticcacheSetMaintainTime(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *models.SElasticcache, task taskman.ITask) error {
  1095. return nil
  1096. }
  1097. func (self *SKVMRegionDriver) RequestElasticcacheAllocatePublicConnection(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error {
  1098. return nil
  1099. }
  1100. func (self *SKVMRegionDriver) RequestElasticcacheReleasePublicConnection(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error {
  1101. return nil
  1102. }
  1103. func (self *SKVMRegionDriver) RequestElasticcacheFlushInstance(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error {
  1104. return nil
  1105. }
  1106. func (self *SKVMRegionDriver) RequestElasticcacheUpdateInstanceParameters(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error {
  1107. return nil
  1108. }
  1109. func (self *SKVMRegionDriver) RequestElasticcacheUpdateBackupPolicy(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error {
  1110. return nil
  1111. }
  1112. func (self *SKVMRegionDriver) ValidateCreateElasticcacheAccountData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
  1113. return nil, nil
  1114. }
  1115. func (self *SKVMRegionDriver) ValidateCreateElasticcacheAclData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
  1116. return nil, nil
  1117. }
  1118. func (self *SKVMRegionDriver) AllowCreateElasticcacheBackup(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, elasticcache *models.SElasticcache) error {
  1119. return fmt.Errorf("not support create kvm elastic cache backup")
  1120. }
  1121. func (self *SKVMRegionDriver) ValidateCreateElasticcacheBackupData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
  1122. return nil, nil
  1123. }
  1124. func (self *SKVMRegionDriver) RequestCreateElasticcacheAccount(ctx context.Context, userCred mcclient.TokenCredential, elasticcacheAccount *models.SElasticcacheAccount, task taskman.ITask) error {
  1125. return nil
  1126. }
  1127. func (self *SKVMRegionDriver) RequestCreateElasticcacheAcl(ctx context.Context, userCred mcclient.TokenCredential, elasticcacheAcl *models.SElasticcacheAcl, task taskman.ITask) error {
  1128. return nil
  1129. }
  1130. func (self *SKVMRegionDriver) RequestCreateElasticcacheBackup(ctx context.Context, userCred mcclient.TokenCredential, elasticcacheBackup *models.SElasticcacheBackup, task taskman.ITask) error {
  1131. return nil
  1132. }
  1133. func (self *SKVMRegionDriver) RequestDeleteElasticcacheAccount(ctx context.Context, userCred mcclient.TokenCredential, ea *models.SElasticcacheAccount, task taskman.ITask) error {
  1134. return nil
  1135. }
  1136. func (self *SKVMRegionDriver) RequestDeleteElasticcacheAcl(ctx context.Context, userCred mcclient.TokenCredential, ea *models.SElasticcacheAcl, task taskman.ITask) error {
  1137. return nil
  1138. }
  1139. func (self *SKVMRegionDriver) RequestDeleteElasticcacheBackup(ctx context.Context, userCred mcclient.TokenCredential, eb *models.SElasticcacheBackup, task taskman.ITask) error {
  1140. return nil
  1141. }
  1142. func (self *SKVMRegionDriver) RequestElasticcacheAccountResetPassword(ctx context.Context, userCred mcclient.TokenCredential, ea *models.SElasticcacheAccount, task taskman.ITask) error {
  1143. return nil
  1144. }
  1145. func (self *SKVMRegionDriver) RequestElasticcacheAclUpdate(ctx context.Context, userCred mcclient.TokenCredential, ea *models.SElasticcacheAcl, task taskman.ITask) error {
  1146. return nil
  1147. }
  1148. func (self *SKVMRegionDriver) RequestElasticcacheBackupRestoreInstance(ctx context.Context, userCred mcclient.TokenCredential, ea *models.SElasticcacheBackup, task taskman.ITask) error {
  1149. return nil
  1150. }
  1151. func (self *SKVMRegionDriver) AllowUpdateElasticcacheAuthMode(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, elasticcache *models.SElasticcache) error {
  1152. return fmt.Errorf("not support update kvm elastic cache auth_mode")
  1153. }
  1154. func (self *SKVMRegionDriver) RequestSyncBucketStatus(ctx context.Context, userCred mcclient.TokenCredential, bucket *models.SBucket, task taskman.ITask) error {
  1155. taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
  1156. iBucket, err := bucket.GetIBucket(ctx)
  1157. if err != nil {
  1158. return nil, errors.Wrap(err, "bucket.GetIBucket")
  1159. }
  1160. return nil, bucket.SetStatus(ctx, userCred, iBucket.GetStatus(), "syncstatus")
  1161. })
  1162. return nil
  1163. }
  1164. func (self *SKVMRegionDriver) IsSupportedElasticcacheSecgroup() bool {
  1165. return false
  1166. }
  1167. func (self *SKVMRegionDriver) GetMaxElasticcacheSecurityGroupCount() int {
  1168. return 0
  1169. }
  1170. func (self *SKVMRegionDriver) RequestDeleteBackup(ctx context.Context, backup *models.SDiskBackup, task taskman.ITask) error {
  1171. backupStorage, err := backup.GetBackupStorage()
  1172. if err != nil {
  1173. return errors.Wrap(err, "unable to get backupStorage")
  1174. }
  1175. host, err := models.HostManager.GetEnabledKvmHostForDiskBackup(backup)
  1176. if err != nil {
  1177. return errors.Wrap(err, "GetEnabledKvmHostForDiskBackup")
  1178. }
  1179. url := fmt.Sprintf("%s/storages/delete-backup", host.ManagerUri)
  1180. body := jsonutils.NewDict()
  1181. body.Set("backup_id", jsonutils.NewString(backup.GetId()))
  1182. body.Set("backup_storage_id", jsonutils.NewString(backupStorage.GetId()))
  1183. accessInfo, err := backupStorage.GetAccessInfo()
  1184. if err != nil {
  1185. return errors.Wrap(err, "GetAccessInfo")
  1186. }
  1187. body.Set("backup_storage_access_info", jsonutils.Marshal(accessInfo))
  1188. header := task.GetTaskRequestHeader()
  1189. _, _, err = httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, header, body, false)
  1190. if err != nil {
  1191. return errors.Wrap(err, "unable to backup")
  1192. }
  1193. return nil
  1194. }
  1195. func (self *SKVMRegionDriver) RequestCreateBackup(ctx context.Context, backup *models.SDiskBackup, snapshotId string, task taskman.ITask) error {
  1196. backupStorage, err := backup.GetBackupStorage()
  1197. if err != nil {
  1198. return errors.Wrap(err, "unable to get backupStorage")
  1199. }
  1200. disk, err := backup.GetDisk()
  1201. if err != nil {
  1202. return errors.Wrap(err, "unable to get disk")
  1203. }
  1204. guest := disk.GetGuest()
  1205. if guest == nil {
  1206. return errors.Wrap(err, "unable to get guest")
  1207. }
  1208. storage, err := disk.GetStorage()
  1209. if err != nil {
  1210. return errors.Wrap(err, "unable to get storage")
  1211. }
  1212. snapshotObj, err := models.SnapshotManager.FetchById(snapshotId)
  1213. if err != nil {
  1214. return errors.Wrap(err, "fetch snapshot")
  1215. }
  1216. snapshot := snapshotObj.(*models.SSnapshot)
  1217. host, _ := guest.GetHost()
  1218. url := fmt.Sprintf("%s/disks/%s/backup/%s", host.ManagerUri, storage.Id, disk.Id)
  1219. body := jsonutils.NewDict()
  1220. body.Set("snapshot_id", jsonutils.NewString(snapshotId))
  1221. if snapshot.Location != "" {
  1222. body.Set("snapshot_location", jsonutils.NewString(snapshot.Location))
  1223. }
  1224. body.Set("backup_id", jsonutils.NewString(backup.GetId()))
  1225. body.Set("backup_storage_id", jsonutils.NewString(backupStorage.GetId()))
  1226. accessInfo, err := backupStorage.GetAccessInfo()
  1227. if err != nil {
  1228. return errors.Wrap(err, "GetAccessInfo")
  1229. }
  1230. body.Set("backup_storage_access_info", jsonutils.Marshal(accessInfo))
  1231. if len(backup.EncryptKeyId) > 0 {
  1232. body.Set("encrypt_key_id", jsonutils.NewString(backup.EncryptKeyId))
  1233. }
  1234. header := task.GetTaskRequestHeader()
  1235. _, _, err = httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, header, body, false)
  1236. if err != nil {
  1237. return errors.Wrap(err, "unable to backup")
  1238. }
  1239. return nil
  1240. }
  1241. func (self *SKVMRegionDriver) RequestAssociateEip(ctx context.Context, userCred mcclient.TokenCredential, eip *models.SElasticip, input api.ElasticipAssociateInput, obj db.IStatusStandaloneModel, task taskman.ITask) error {
  1242. taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
  1243. if err := eip.AssociateInstance(ctx, userCred, input.InstanceType, obj); err != nil {
  1244. return nil, errors.Wrapf(err, "associate eip %s(%s) to %s %s(%s)", eip.Name, eip.Id, obj.Keyword(), obj.GetName(), obj.GetId())
  1245. }
  1246. switch input.InstanceType {
  1247. case api.EIP_ASSOCIATE_TYPE_SERVER:
  1248. err := self.requestAssociateEipWithServer(ctx, userCred, eip, input, obj, task)
  1249. if err != nil {
  1250. return nil, err
  1251. }
  1252. case api.EIP_ASSOCIATE_TYPE_INSTANCE_GROUP:
  1253. err := self.requestAssociateEipWithInstanceGroup(ctx, userCred, eip, input, obj, task)
  1254. if err != nil {
  1255. return nil, err
  1256. }
  1257. case api.EIP_ASSOCIATE_TYPE_LOADBALANCER:
  1258. err := self.requestAssociateEipWithLoadbalancer(ctx, userCred, eip, input, obj, task)
  1259. if err != nil {
  1260. return nil, err
  1261. }
  1262. default:
  1263. return nil, errors.Wrapf(cloudprovider.ErrNotSupported, "instance type %s", input.InstanceType)
  1264. }
  1265. if err := eip.SetStatus(ctx, userCred, api.EIP_STATUS_READY, api.EIP_STATUS_ASSOCIATE); err != nil {
  1266. return nil, errors.Wrapf(err, "set eip status to %s", api.EIP_STATUS_READY)
  1267. }
  1268. return nil, nil
  1269. })
  1270. return nil
  1271. }
  1272. func (self *SKVMRegionDriver) requestAssociateEipWithServer(ctx context.Context, userCred mcclient.TokenCredential, eip *models.SElasticip, input api.ElasticipAssociateInput, obj db.IStatusStandaloneModel, task taskman.ITask) error {
  1273. guest := obj.(*models.SGuest)
  1274. hps := sets.NewString(api.HYPERVISOR_KVM, api.HYPERVISOR_POD)
  1275. if !hps.Has(guest.GetHypervisor()) {
  1276. return errors.Wrapf(cloudprovider.ErrNotSupported, "not support associate eip for hypervisor %s", guest.GetHypervisor())
  1277. }
  1278. lockman.LockObject(ctx, guest)
  1279. defer lockman.ReleaseObject(ctx, guest)
  1280. var guestnics []models.SGuestnetwork
  1281. {
  1282. netq := models.NetworkManager.Query().SubQuery()
  1283. wirq := models.WireManager.Query().SubQuery()
  1284. vpcq := models.VpcManager.Query().SubQuery()
  1285. gneq := models.GuestnetworkManager.Query()
  1286. q := gneq.Equals("guest_id", guest.Id).
  1287. IsNullOrEmpty("eip_id")
  1288. if len(input.IpAddr) > 0 {
  1289. q = q.Equals("ip_addr", input.IpAddr)
  1290. }
  1291. q = q.Join(netq, sqlchemy.Equals(netq.Field("id"), gneq.Field("network_id")))
  1292. q = q.Join(wirq, sqlchemy.Equals(wirq.Field("id"), netq.Field("wire_id")))
  1293. q = q.Join(vpcq, sqlchemy.Equals(vpcq.Field("id"), wirq.Field("vpc_id")))
  1294. q = q.Filter(sqlchemy.NotEquals(vpcq.Field("id"), api.DEFAULT_VPC_ID))
  1295. if err := db.FetchModelObjects(models.GuestnetworkManager, q, &guestnics); err != nil {
  1296. return errors.Wrapf(err, "db.FetchModelObjects")
  1297. }
  1298. if len(guestnics) == 0 {
  1299. return errors.Errorf("guest has no nics to associate eip")
  1300. }
  1301. }
  1302. guestnic := &guestnics[0]
  1303. lockman.LockObject(ctx, guestnic)
  1304. defer lockman.ReleaseObject(ctx, guestnic)
  1305. if _, err := db.Update(guestnic, func() error {
  1306. guestnic.EipId = eip.Id
  1307. return nil
  1308. }); err != nil {
  1309. return errors.Wrapf(err, "set associated eip for guestnic %s (guest:%s, network:%s)",
  1310. guestnic.Ifname, guestnic.GuestId, guestnic.NetworkId)
  1311. }
  1312. return nil
  1313. }
  1314. func (self *SKVMRegionDriver) requestAssociateEipWithInstanceGroup(ctx context.Context, userCred mcclient.TokenCredential, eip *models.SElasticip, input api.ElasticipAssociateInput, obj db.IStatusStandaloneModel, task taskman.ITask) error {
  1315. group := obj.(*models.SGroup)
  1316. lockman.LockObject(ctx, group)
  1317. defer lockman.ReleaseObject(ctx, group)
  1318. var groupnics []models.SGroupnetwork
  1319. {
  1320. gneq := models.GroupnetworkManager.Query()
  1321. q := gneq.Equals("group_id", group.Id).
  1322. IsNullOrEmpty("eip_id")
  1323. if len(input.IpAddr) > 0 {
  1324. q = q.Equals("ip_addr", input.IpAddr)
  1325. }
  1326. if err := db.FetchModelObjects(models.GroupnetworkManager, q, &groupnics); err != nil {
  1327. return errors.Wrapf(err, "db.FetchModelObjects")
  1328. }
  1329. if len(groupnics) == 0 {
  1330. return errors.Errorf("instance group has no nics to associate eip")
  1331. }
  1332. }
  1333. groupnic := &groupnics[0]
  1334. lockman.LockObject(ctx, groupnic)
  1335. defer lockman.ReleaseObject(ctx, groupnic)
  1336. if _, err := db.Update(groupnic, func() error {
  1337. groupnic.EipId = eip.Id
  1338. return nil
  1339. }); err != nil {
  1340. return errors.Wrapf(err, "set associated eip for groupnic %s/%s (guest:%s, network:%s)",
  1341. groupnic.IpAddr, groupnic.Ip6Addr, groupnic.GroupId, groupnic.NetworkId)
  1342. }
  1343. return nil
  1344. }
  1345. func (self *SKVMRegionDriver) requestAssociateEipWithLoadbalancer(
  1346. ctx context.Context,
  1347. userCred mcclient.TokenCredential,
  1348. eip *models.SElasticip,
  1349. input api.ElasticipAssociateInput,
  1350. obj db.IStatusStandaloneModel,
  1351. task taskman.ITask,
  1352. ) error {
  1353. lb := obj.(*models.SLoadbalancer)
  1354. if _, err := db.Update(lb, func() error {
  1355. lb.Address = eip.IpAddr
  1356. lb.AddressType = api.LB_ADDR_TYPE_INTERNET
  1357. return nil
  1358. }); err != nil {
  1359. return errors.Wrap(err, "set loadbalancer address")
  1360. }
  1361. if err := eip.AssociateLoadbalancer(ctx, userCred, lb); err != nil {
  1362. return errors.Wrapf(err, "associate eip %s(%s) to loadbalancer %s(%s)", eip.Name, eip.Id, lb.Name, lb.Id)
  1363. }
  1364. if err := eip.SetStatus(ctx, userCred, api.EIP_STATUS_READY, api.EIP_STATUS_ASSOCIATE); err != nil {
  1365. return errors.Wrapf(err, "set eip status to %s", api.EIP_STATUS_ALLOCATE)
  1366. }
  1367. return nil
  1368. }
  1369. func (self *SKVMRegionDriver) RequestCreateSecurityGroup(
  1370. ctx context.Context,
  1371. userCred mcclient.TokenCredential,
  1372. secgroup *models.SSecurityGroup,
  1373. rules api.SSecgroupRuleResourceSet,
  1374. ) error {
  1375. _, err := db.Update(secgroup, func() error {
  1376. secgroup.VpcId = ""
  1377. return nil
  1378. })
  1379. if err != nil {
  1380. return err
  1381. }
  1382. for _, r := range rules {
  1383. rule := &models.SSecurityGroupRule{
  1384. Priority: int(*r.Priority),
  1385. Protocol: r.Protocol,
  1386. Ports: r.Ports,
  1387. Direction: r.Direction,
  1388. CIDR: r.CIDR,
  1389. Action: r.Action,
  1390. Description: r.Description,
  1391. }
  1392. rule.SecgroupId = secgroup.Id
  1393. models.SecurityGroupRuleManager.TableSpec().Insert(ctx, rule)
  1394. }
  1395. secgroup.SetStatus(ctx, userCred, api.SECGROUP_STATUS_READY, "")
  1396. return nil
  1397. }
  1398. func (self *SKVMRegionDriver) RequestPrepareSecurityGroups(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, secgroups []models.SSecurityGroup, vpc *models.SVpc, callback func(ids []string) error, task taskman.ITask) error {
  1399. return task.ScheduleRun(nil)
  1400. }
  1401. func (self *SKVMRegionDriver) RequestDeleteSecurityGroup(ctx context.Context, userCred mcclient.TokenCredential, secgroup *models.SSecurityGroup, task taskman.ITask) error {
  1402. return task.ScheduleRun(nil)
  1403. }
  1404. func (self *SKVMRegionDriver) GetSecurityGroupFilter(vpc *models.SVpc) (func(q *sqlchemy.SQuery) *sqlchemy.SQuery, error) {
  1405. return func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  1406. return q.Equals("cloudregion_id", api.DEFAULT_REGION_ID)
  1407. }, nil
  1408. }
  1409. func (self *SKVMRegionDriver) ValidateUpdateSecurityGroupRuleInput(ctx context.Context, userCred mcclient.TokenCredential, input *api.SSecgroupRuleUpdateInput) (*api.SSecgroupRuleUpdateInput, error) {
  1410. if input.Priority != nil {
  1411. if *input.Priority < 1 || *input.Priority > 100 {
  1412. return nil, httperrors.NewInputParameterError("invalid priority %d", input.Priority)
  1413. }
  1414. }
  1415. if input.Action != nil {
  1416. if !utils.IsInStringArray(*input.Action, []string{string(secrules.SecurityRuleAllow), string(secrules.SecurityRuleDeny)}) {
  1417. return nil, httperrors.NewInputParameterError("invalid action %s", *input.Action)
  1418. }
  1419. }
  1420. if input.Protocol != nil {
  1421. if !utils.IsInStringArray(*input.Protocol, []string{
  1422. secrules.PROTO_ANY,
  1423. secrules.PROTO_UDP,
  1424. secrules.PROTO_TCP,
  1425. secrules.PROTO_ICMP,
  1426. }) {
  1427. return nil, httperrors.NewInputParameterError("invalid protocol %s", *input.Protocol)
  1428. }
  1429. }
  1430. if input.Ports != nil {
  1431. rule := secrules.SecurityRule{}
  1432. err := rule.ParsePorts(*input.Ports)
  1433. if err != nil {
  1434. return nil, httperrors.NewInputParameterError("invalid ports %s", *input.Ports)
  1435. }
  1436. }
  1437. if input.CIDR != nil && len(*input.CIDR) > 0 && !regutils.MatchCIDR(*input.CIDR) && !regutils.MatchIP4Addr(*input.CIDR) && !regutils.MatchCIDR6(*input.CIDR) && !regutils.MatchIP6Addr(*input.CIDR) {
  1438. return nil, httperrors.NewInputParameterError("invalid cidr %s", *input.CIDR)
  1439. }
  1440. return input, nil
  1441. }
  1442. func (self *SKVMRegionDriver) ValidateCreateSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, region *models.SCloudregion, input *api.SSnapshotPolicyCreateInput) (*api.SSnapshotPolicyCreateInput, error) {
  1443. return input, nil
  1444. }
  1445. func (self *SKVMRegionDriver) RequestCreateSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, region *models.SCloudregion, sp *models.SSnapshotPolicy, task taskman.ITask) error {
  1446. sp.SetStatus(ctx, userCred, apis.STATUS_AVAILABLE, "")
  1447. return task.ScheduleRun(nil)
  1448. }
  1449. func (self *SKVMRegionDriver) RequestDeleteSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, region *models.SCloudregion, sp *models.SSnapshotPolicy, task taskman.ITask) error {
  1450. return task.ScheduleRun(nil)
  1451. }
  1452. func (self *SKVMRegionDriver) RequestSnapshotPolicyBindDisks(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, diskIds []string, task taskman.ITask) error {
  1453. taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
  1454. disks, err := sp.GetUnbindDisks(diskIds)
  1455. if err != nil {
  1456. return nil, errors.Wrapf(err, "GetUnbindDisks")
  1457. }
  1458. ids := []string{}
  1459. for _, disk := range disks {
  1460. ids = append(ids, disk.Id)
  1461. }
  1462. return nil, sp.BindDisks(ctx, disks)
  1463. })
  1464. return nil
  1465. }
  1466. func (self *SKVMRegionDriver) RequestSnapshotPolicyUnbindDisks(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, diskIds []string, task taskman.ITask) error {
  1467. taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
  1468. return nil, sp.UnbindDisks(diskIds)
  1469. })
  1470. return nil
  1471. }