remotefile.go 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  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 remotefile
  15. import (
  16. "context"
  17. "fmt"
  18. "net/http"
  19. "sync"
  20. "yunion.io/x/jsonutils"
  21. "yunion.io/x/pkg/util/httputils"
  22. api "yunion.io/x/cloudmux/pkg/apis/compute"
  23. "yunion.io/x/cloudmux/pkg/cloudprovider"
  24. )
  25. const (
  26. CLOUD_PROVIDER_REMOTEFILE = api.CLOUD_PROVIDER_REMOTEFILE
  27. )
  28. type RemoteFileClientConfig struct {
  29. cpcfg cloudprovider.ProviderConfig
  30. url string
  31. username string
  32. password string
  33. client *http.Client
  34. projects []SProject
  35. regions []SRegion
  36. zones []SZone
  37. wires []SWire
  38. networks []SNetwork
  39. storages []SStorage
  40. disks []SDisk
  41. hosts []SHost
  42. vpcs []SVpc
  43. vms []SInstance
  44. buckets []SBucket
  45. eips []SEip
  46. rds []SDBInstance
  47. lbs []SLoadbalancer
  48. misc []SMisc
  49. secgroups []SSecurityGroup
  50. metrics []map[cloudprovider.TMetricType]map[string]interface{}
  51. debug bool
  52. }
  53. func NewRemoteFileClientConfig(url, username, password string) *RemoteFileClientConfig {
  54. cfg := &RemoteFileClientConfig{
  55. url: url,
  56. username: username,
  57. password: password,
  58. }
  59. return cfg
  60. }
  61. func (cfg *RemoteFileClientConfig) CloudproviderConfig(cpcfg cloudprovider.ProviderConfig) *RemoteFileClientConfig {
  62. cfg.cpcfg = cpcfg
  63. return cfg
  64. }
  65. func (cfg *RemoteFileClientConfig) Debug(debug bool) *RemoteFileClientConfig {
  66. cfg.debug = debug
  67. return cfg
  68. }
  69. type SRemoteFileClient struct {
  70. *RemoteFileClientConfig
  71. lock sync.Mutex
  72. }
  73. func NewRemoteFileClient(cfg *RemoteFileClientConfig) (*SRemoteFileClient, error) {
  74. cli := &SRemoteFileClient{
  75. RemoteFileClientConfig: cfg,
  76. }
  77. cli.client = httputils.GetDefaultClient()
  78. if cli.cpcfg.ProxyFunc != nil {
  79. httputils.SetClientProxyFunc(cli.client, cli.cpcfg.ProxyFunc)
  80. }
  81. _, err := cli.GetRegions()
  82. return cli, err
  83. }
  84. func (cli *SRemoteFileClient) GetCloudRegionExternalIdPrefix() string {
  85. return fmt.Sprintf("%s/%s", CLOUD_PROVIDER_REMOTEFILE, cli.cpcfg.Id)
  86. }
  87. func (cli *SRemoteFileClient) GetSubAccounts() ([]cloudprovider.SSubAccount, error) {
  88. subAccount := cloudprovider.SSubAccount{
  89. Account: cli.cpcfg.Id,
  90. Name: cli.cpcfg.Name,
  91. Id: cli.cpcfg.Id,
  92. HealthStatus: api.CLOUD_PROVIDER_HEALTH_NORMAL,
  93. }
  94. return []cloudprovider.SSubAccount{subAccount}, nil
  95. }
  96. func (self *SRemoteFileClient) _url(res string) string {
  97. return fmt.Sprintf("%s/%s.json", self.url, res)
  98. }
  99. func (self *SRemoteFileClient) get(res string) (jsonutils.JSONObject, error) {
  100. _, resp, err := httputils.JSONRequest(self.client, context.Background(), httputils.GET, self._url(res), nil, nil, self.debug)
  101. if err != nil {
  102. return nil, err
  103. }
  104. return resp, nil
  105. }
  106. func (self *SRemoteFileClient) GetRegions() ([]SRegion, error) {
  107. if len(self.regions) > 0 {
  108. return self.regions, nil
  109. }
  110. self.regions = []SRegion{}
  111. resp, err := self.get("regions")
  112. if err != nil {
  113. return nil, err
  114. }
  115. return self.regions, resp.Unmarshal(&self.regions)
  116. }
  117. func (self *SRemoteFileClient) GetVpcs() ([]SVpc, error) {
  118. if len(self.vpcs) > 0 {
  119. return self.vpcs, nil
  120. }
  121. self.vpcs = []SVpc{}
  122. resp, err := self.get("vpcs")
  123. if err != nil {
  124. return nil, err
  125. }
  126. return self.vpcs, resp.Unmarshal(&self.vpcs)
  127. }
  128. func (self *SRemoteFileClient) GetMisc() ([]SMisc, error) {
  129. if len(self.misc) > 0 {
  130. return self.misc, nil
  131. }
  132. self.misc = []SMisc{}
  133. resp, err := self.get("misc")
  134. if err != nil {
  135. return nil, err
  136. }
  137. return self.misc, resp.Unmarshal(&self.misc)
  138. }
  139. func (self *SRemoteFileClient) GetSecgroups() ([]SSecurityGroup, error) {
  140. if len(self.secgroups) > 0 {
  141. return self.secgroups, nil
  142. }
  143. self.secgroups = []SSecurityGroup{}
  144. resp, err := self.get("secgroups")
  145. if err != nil {
  146. return nil, err
  147. }
  148. return self.secgroups, resp.Unmarshal(&self.secgroups)
  149. }
  150. func (self *SRemoteFileClient) GetInstances() ([]SInstance, error) {
  151. if len(self.vms) > 0 {
  152. return self.vms, nil
  153. }
  154. self.vms = []SInstance{}
  155. resp, err := self.get("instances")
  156. if err != nil {
  157. return nil, err
  158. }
  159. return self.vms, resp.Unmarshal(&self.vms)
  160. }
  161. func (self *SRemoteFileClient) GetBuckets() ([]SBucket, error) {
  162. if len(self.buckets) > 0 {
  163. return self.buckets, nil
  164. }
  165. self.buckets = []SBucket{}
  166. resp, err := self.get("buckets")
  167. if err != nil {
  168. return nil, err
  169. }
  170. return self.buckets, resp.Unmarshal(&self.buckets)
  171. }
  172. func (self *SRemoteFileClient) GetEips() ([]SEip, error) {
  173. if len(self.eips) > 0 {
  174. return self.eips, nil
  175. }
  176. self.eips = []SEip{}
  177. resp, err := self.get("eips")
  178. if err != nil {
  179. return nil, err
  180. }
  181. return self.eips, resp.Unmarshal(&self.eips)
  182. }
  183. func (self *SRemoteFileClient) GetDBInstances() ([]SDBInstance, error) {
  184. if len(self.rds) > 0 {
  185. return self.rds, nil
  186. }
  187. self.rds = []SDBInstance{}
  188. resp, err := self.get("dbinstances")
  189. if err != nil {
  190. return nil, err
  191. }
  192. return self.rds, resp.Unmarshal(&self.rds)
  193. }
  194. func (self *SRemoteFileClient) GetLoadbalancers() ([]SLoadbalancer, error) {
  195. if len(self.lbs) > 0 {
  196. return self.lbs, nil
  197. }
  198. self.lbs = []SLoadbalancer{}
  199. resp, err := self.get("loadbalancers")
  200. if err != nil {
  201. return nil, err
  202. }
  203. return self.lbs, resp.Unmarshal(&self.lbs)
  204. }
  205. func (self *SRemoteFileClient) GetIRegions() ([]cloudprovider.ICloudRegion, error) {
  206. ret := []cloudprovider.ICloudRegion{}
  207. for i := range self.regions {
  208. self.regions[i].client = self
  209. ret = append(ret, &self.regions[i])
  210. }
  211. return ret, nil
  212. }
  213. func (self *SRemoteFileClient) GetIRegionById(id string) (cloudprovider.ICloudRegion, error) {
  214. regions, err := self.GetIRegions()
  215. if err != nil {
  216. return nil, err
  217. }
  218. for i := range regions {
  219. if regions[i].GetGlobalId() == id {
  220. return regions[i], nil
  221. }
  222. }
  223. return nil, cloudprovider.ErrNotFound
  224. }
  225. func (self *SRemoteFileClient) GetZones() ([]SZone, error) {
  226. if len(self.zones) > 0 {
  227. return self.zones, nil
  228. }
  229. self.zones = []SZone{}
  230. resp, err := self.get("zones")
  231. if err != nil {
  232. return nil, err
  233. }
  234. return self.zones, resp.Unmarshal(&self.zones)
  235. }
  236. func (self *SRemoteFileClient) GetHosts() ([]SHost, error) {
  237. if len(self.hosts) > 0 {
  238. return self.hosts, nil
  239. }
  240. self.hosts = []SHost{}
  241. resp, err := self.get("hosts")
  242. if err != nil {
  243. return nil, err
  244. }
  245. return self.hosts, resp.Unmarshal(&self.hosts)
  246. }
  247. func (self *SRemoteFileClient) GetStorages() ([]SStorage, error) {
  248. if len(self.storages) > 0 {
  249. return self.storages, nil
  250. }
  251. self.storages = []SStorage{}
  252. resp, err := self.get("storages")
  253. if err != nil {
  254. return nil, err
  255. }
  256. return self.storages, resp.Unmarshal(&self.storages)
  257. }
  258. func (self *SRemoteFileClient) getMetrics(resourceType cloudprovider.TResourceType, metricType cloudprovider.TMetricType) ([]cloudprovider.MetricValues, error) {
  259. ret := []cloudprovider.MetricValues{}
  260. self.lock.Lock()
  261. defer self.lock.Unlock()
  262. if self.metrics == nil {
  263. self.metrics = []map[cloudprovider.TMetricType]map[string]interface{}{}
  264. resp, err := self.get("metrics")
  265. if err != nil {
  266. return nil, err
  267. }
  268. err = resp.Unmarshal(&self.metrics)
  269. if err != nil {
  270. return nil, err
  271. }
  272. }
  273. for _, metric := range self.metrics {
  274. values, ok := metric[metricType]
  275. if ok {
  276. mid := cloudprovider.MetricValues{}
  277. jsonutils.Update(&mid, values)
  278. ret = append(ret, mid)
  279. }
  280. }
  281. return ret, nil
  282. }
  283. func (self *SRemoteFileClient) GetWires() ([]SWire, error) {
  284. if len(self.wires) > 0 {
  285. return self.wires, nil
  286. }
  287. self.wires = []SWire{}
  288. resp, err := self.get("wires")
  289. if err != nil {
  290. return nil, err
  291. }
  292. return self.wires, resp.Unmarshal(&self.wires)
  293. }
  294. func (self *SRemoteFileClient) GetNetworks() ([]SNetwork, error) {
  295. if len(self.networks) > 0 {
  296. return self.networks, nil
  297. }
  298. self.networks = []SNetwork{}
  299. resp, err := self.get("networks")
  300. if err != nil {
  301. return nil, err
  302. }
  303. return self.networks, resp.Unmarshal(&self.networks)
  304. }
  305. func (self *SRemoteFileClient) GetDisks() ([]SDisk, error) {
  306. if len(self.disks) > 0 {
  307. return self.disks, nil
  308. }
  309. self.disks = []SDisk{}
  310. resp, err := self.get("disks")
  311. if err != nil {
  312. return nil, err
  313. }
  314. return self.disks, resp.Unmarshal(&self.disks)
  315. }
  316. func (self *SRemoteFileClient) GetProjects() ([]SProject, error) {
  317. if len(self.projects) > 0 {
  318. return self.projects, nil
  319. }
  320. resp, err := self.get("projects")
  321. if err != nil {
  322. return nil, err
  323. }
  324. self.projects = []SProject{}
  325. return self.projects, resp.Unmarshal(&self.projects)
  326. }
  327. func (self *SRemoteFileClient) GetIProjects() ([]cloudprovider.ICloudProject, error) {
  328. projects, err := self.GetProjects()
  329. if err != nil {
  330. return nil, err
  331. }
  332. ret := []cloudprovider.ICloudProject{}
  333. for i := range projects {
  334. ret = append(ret, &projects[i])
  335. }
  336. return ret, nil
  337. }
  338. func (self *SRemoteFileClient) GetCapabilities() []string {
  339. caps := []string{
  340. cloudprovider.CLOUD_CAPABILITY_PROJECT + cloudprovider.READ_ONLY_SUFFIX,
  341. cloudprovider.CLOUD_CAPABILITY_COMPUTE + cloudprovider.READ_ONLY_SUFFIX,
  342. cloudprovider.CLOUD_CAPABILITY_NETWORK + cloudprovider.READ_ONLY_SUFFIX,
  343. cloudprovider.CLOUD_CAPABILITY_SECURITY_GROUP + cloudprovider.READ_ONLY_SUFFIX,
  344. cloudprovider.CLOUD_CAPABILITY_EIP + cloudprovider.READ_ONLY_SUFFIX,
  345. cloudprovider.CLOUD_CAPABILITY_LOADBALANCER + cloudprovider.READ_ONLY_SUFFIX,
  346. cloudprovider.CLOUD_CAPABILITY_QUOTA + cloudprovider.READ_ONLY_SUFFIX,
  347. cloudprovider.CLOUD_CAPABILITY_OBJECTSTORE + cloudprovider.READ_ONLY_SUFFIX,
  348. cloudprovider.CLOUD_CAPABILITY_RDS + cloudprovider.READ_ONLY_SUFFIX,
  349. cloudprovider.CLOUD_CAPABILITY_CACHE + cloudprovider.READ_ONLY_SUFFIX,
  350. cloudprovider.CLOUD_CAPABILITY_MISC + cloudprovider.READ_ONLY_SUFFIX,
  351. }
  352. return caps
  353. }