mos_sdk 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/lib/mos_sdk.rb +315 -0
  3. data/lib/mos_sdk/base.rb +169 -0
  4. metadata +74 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3062a341e10d50c0ba53d12da98907ab862f1af2
4
+ data.tar.gz: 0f471fcf2b040f8e479eefcf633adc72bef26b1c
5
+ SHA512:
6
+ metadata.gz: a4e495643cc5c6aef94d7a01be978568359b2398ade1e1174bb9bb3dd51ada331e946c968ab6724a47f4efabb8ef99a30b96ee941e8b4473c9215e743ab522cd
7
+ data.tar.gz: 7784e038edbe6f6a7332a492a97fe3eefb3b2a31b08d13e687dd95d3bad5217d117919f2c9b338d2188c2f2b1ea4704f38bcef1c5ce119cfcdd284f22e78709d
@@ -0,0 +1,315 @@
1
+ # -*- coding: utf-8 -*-
2
+ $:.unshift File.join(File.dirname(__FILE__), '.', 'mos_sdk')
3
+ require 'base.rb'
4
+
5
+ module MosSdk
6
+ class Client < MosSdk::Base
7
+ end
8
+ end
9
+
10
+ # 基类函数为Base,mos_sdk的实现类
11
+ class MosSdk::Client
12
+ # 构造函数
13
+ def initialize(access, secret, url, format='xml', timeout=300, debug=false)
14
+ super(access, secret, url, format, timeout, debug)
15
+ end
16
+
17
+ # 获取所有虚拟机类型
18
+ # - @param [Integer] limit 最大返回数量,用于分页控制
19
+ # - @param [Integer] offset 返回偏移量,用于分页控制
20
+ # - @param [Hash] filters 过滤条件,key/value分别指定过滤字段名称和值,支持的字段名称为:name, status
21
+ # - @return [Hash] 所有虚拟机信息
22
+ def describe_instance_types(limit=0, offset=0, filters=nil)
23
+ kwargs = {}
24
+ self.parse_array_params(limit, offset, filters, kwargs) # parse_list_params 父类函数
25
+ val = self.request('DescribeInstanceTypes', *kwargs)
26
+ val['InstanceTypeSet']
27
+ end
28
+
29
+ # 获得所有虚拟机模板
30
+ # - @return [Hash] 模板列表
31
+ def describe_templates()
32
+ val = self.request('DescribeTemplates')
33
+ val['TemplateSet']
34
+ end
35
+
36
+ # 获取帐户余额和最近更新时间
37
+ # - @return [Hash] 帐户余额和最近更新时间
38
+ def get_balance()
39
+ self.request('GetBalance')
40
+ end
41
+
42
+ # 获得所有虚拟机
43
+ # - @param [Array] ids 期望获取的虚拟机ID列表
44
+ # - @param [Array] names 期望获取信息的虚拟机名称列表
45
+ # - @param [Integer] limit 最多返回数量
46
+ # - @param [Integer] offset 返回虚拟机的偏移量,用于分页显示
47
+ # - @param [Hash] filters 过滤器,一个hash,包含过滤字段名和值,可能过滤字段为:name, status
48
+ # - @return [Hash] 虚拟机列表
49
+ def describe_instances(ids=nil, names=nil, limit=0, offset=0, filters=nil)
50
+ kwargs = {}
51
+ kwargs['InstanceId'] = ids if ids.kind_of?(Array) && ids.size() > 0
52
+ kwargs['InstanceName'] = names if names.kind_of?(Array) && names.size() > 0
53
+ self.parse_array_params(limit, offset, filters, kwargs)
54
+ val = self.request('DescribeInstances', *kwargs)
55
+ val['InstanceSet']
56
+ end
57
+
58
+ # 获取指定虚拟机的虚拟磁盘信息
59
+ # - @param [String] iid 虚拟机ID
60
+ # - @param [Integer] limit 最大返回数量,用于分页控制
61
+ # - @param [Integer] offset 返回的偏移量,用于分页控制
62
+ # - @param [Hash] filters 返回结果过滤条件,由hash的key/value指定过滤字段名和值
63
+ # - @return [Hash] 指定虚拟机磁盘列表
64
+ def describe_instance_volumes(iid, limit=0, offset=0, filters=nil)
65
+ kwargs = {}
66
+ kwargs['InstanceId'] = iid
67
+ self.parse_array_params(limit, offset, filters, kwargs)
68
+ val = self.request('DescribeInstanceVolumes', *kwargs)
69
+ val['InstanceVolumeSet']
70
+ end
71
+
72
+ # 获取指定虚拟机的网络接口(虚拟网卡)信息
73
+ # - @param [String] iid 虚拟机ID
74
+ # - @param [Integer] limit 最大返回数量,用于分页控制
75
+ # - @param [Integer] offset 返回的偏移量,用于分页控制
76
+ # - @param [Hash] filters 返回结果过滤条件,由hash的key/value指定过滤字段名和值
77
+ # - @return [Hash] 指定虚拟机的网络接口(虚拟网卡)信息
78
+ def describe_network_interfaces(iid, limit=0, offset=0, filters=nil)
79
+ kwargs = {}
80
+ kwargs['InstanceId'] = iid
81
+ self.parse_array_params(limit, offset, filters, kwargs)
82
+ val = self.request('DescribeInstanceNetworkInterfaces', *kwargs)
83
+ val['InstanceNetworkInterfaceSet']
84
+ end
85
+
86
+ # 虚拟机租期续费
87
+ # - @param [String] iid 虚拟机ID
88
+ # - @param [String] duration 续费租期,缺省为'1M',即一个月
89
+ def renew_instance(iid, duration=nil)
90
+ kwargs = {}
91
+ kwargs['InstanceId'] = iid
92
+ unless duration.nil?
93
+ (/^\d+[HhMm]$/.match(duration)) ? (kwargs['Duration'] = duration) : (raise Exception("Illegal duration %s" % duration))
94
+ end
95
+ self.request('RenewInstance', *kwargs)
96
+ end
97
+
98
+ # 获取虚拟机的租期信息
99
+ # - @param [String] iid 虚拟机ID
100
+ # - @return [Hash] 虚拟机租期信息,包含过期时间、自动删除时间
101
+ def get_instance_contract_info(iid)
102
+ kwargs = {}
103
+ kwargs['InstanceId'] = iid
104
+ self.request('GetInstanceContractInfo', *kwargs)
105
+ end
106
+
107
+ # 创建虚拟机,创建时要提供datadisk和bandwidth参数
108
+ # - @param [String] imageid 系统模板ID
109
+ # - @param [String] itype 虚拟机类型ID 例如 C4_M4 代表四核 4G内存
110
+ # - @param [String] duration 虚拟机租期, 缺省为'1M',即一个月
111
+ # - @param [String] name 虚拟机名称(可选)
112
+ # - @param [String] keypair 虚拟机使用的SSH密钥ID
113
+ # - @param [Integer] datadisk 指定创建虚拟机使用的额外数据盘,单位为1GB
114
+ # - @param [Integer] bandwidth 指定创建虚拟机使用的额外带宽,单位为Mbps
115
+ # - @return [Hash] 创建成功的虚拟机信息
116
+ def create_instance(imageid, itype, duration=nil, name=nil, keypair=nil, datadisk=nil, bandwidth=nil)
117
+ kwargs = {}
118
+ kwargs['ImageId'] = imageid
119
+ kwargs['InstanceType'] = itype
120
+ unless duration.nil?
121
+ /^\d+[HhMm]$/.match(duration) ? kwargs['Duration'] = duration : (raise Exception('Illegal duration format'))
122
+ end
123
+
124
+ kwargs['InstanceName'] = name unless name.nil?
125
+ kwargs['KeyName'] = keypair unless keypair.nil?
126
+ kwargs['ExtraExtDisksize'] = datadisk unless datadisk.nil?
127
+ kwargs['ExtraExtBandwidth'] = bandwidth unless bandwidth.nil?
128
+ val = self.request('CreateInstance', *kwargs)
129
+ val['Instance']
130
+ end
131
+
132
+ # 获取虚拟机的状态
133
+ # - @param [String] iid 虚拟机ID
134
+ # - @return [Hash] 虚拟机状态
135
+ def describe_instance_status(iid)
136
+ kwargs = {}
137
+ kwargs['InstanceId'] = iid
138
+ val = self.request('DescribeInstanceStatus', *kwargs)
139
+ val['InstanceStatus']
140
+ end
141
+
142
+ # 获取虚拟机的Login帐户信息
143
+ # - @param [String] iid 虚拟机ID
144
+ # - @param [String] key_file 私钥文件路径,如果虚拟机使用了SSH密钥,需要指定私钥解密password
145
+ # - @return [Hash] 虚拟机Login信息,包含帐户名称、密码,如果使用SSH密钥,则还包含密钥ID和名称
146
+ def get_password_data(iid, key_file=nil)
147
+ kwargs = {}
148
+ kwargs['InstanceId'] = iid
149
+ val = self.request('GetPasswordData', *kwargs)
150
+ if val.has_key?('passwordData') && val.has_key?('keypairName')
151
+ if key_file.nil?
152
+ raise Exception('Password is encrypted, please specify private key of keypair %s' % val['keypairName'])
153
+ else
154
+ begin
155
+ f = open(key_file)
156
+ rescue
157
+ puts 'fail to open file'
158
+ exit(-1)
159
+ end
160
+
161
+ key = f.read()
162
+ f.close()
163
+ val['passwordData']=Base64.decode64(
164
+ OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), key, val['passwordData'])
165
+ ).strip
166
+ end
167
+ end
168
+ val
169
+ end
170
+
171
+ # 启动虚拟机
172
+ # - @param [String] iid 虚拟机ID
173
+ def start_instance(iid)
174
+ kwargs = {}
175
+ kwargs['InstanceId'] = iid
176
+ self.request('StartInstance', *kwargs)
177
+ end
178
+
179
+ # 停止虚拟机
180
+ # - @param [String] iid 虚拟机ID
181
+ # - @param [] force 是否强制停止虚拟机
182
+ def stop_instance(iid, force=false)
183
+ kwargs = {}
184
+ kwargs['InstanceId'] = iid
185
+ kwargs['Force'] = force if force
186
+ self.request('StopInstance', *kwargs)
187
+ end
188
+
189
+ # 重启虚拟机
190
+ # - @param [String] iid 虚拟机ID
191
+ def reboot_instance(iid)
192
+ kwargs = {}
193
+ kwargs['InstanceId'] = iid
194
+ self.request('RebootInstance', *kwargs)
195
+ end
196
+
197
+ # 删除虚拟机
198
+ # - @param [String] iid 虚拟机ID
199
+ def terminate_instance(iid)
200
+ kwargs = {}
201
+ kwargs['InstanceId'] = iid
202
+ self.request('TerminateInstance', *kwargs)
203
+ end
204
+
205
+ # 重置虚拟机系统磁盘
206
+ # - @param [String] iid 虚拟机ID
207
+ # - @param [String] image_id 将虚拟机系统磁盘用指定镜像模板重置,如果无该参数,则使用原镜像模板重置
208
+ def rebuild_instance_root_image(iid, image_id=nil)
209
+ kwargs = {}
210
+ kwargs['InstanceId'] = iid
211
+ kwargs['ImageId'] = image_id if !(image_id.nil?) && image_id.size > 0
212
+ self.request('RebuildInstanceRootImage', *kwargs)
213
+ end
214
+
215
+ # 更改虚拟机类型
216
+ # - @param [String] iid 虚拟机ID
217
+ # - @param [String] itype 指定更改的虚拟机类型
218
+ # - @param [String] duration 指定更改后的初始租期,缺省为'1M',即一个月
219
+ # - @param [Integer] datadisk 指定创建虚拟机使用的额外数据盘,单位为1GB
220
+ # - @param [Integer] bandwidth 指定创建虚拟机使用的额外带宽,单位为Mbps
221
+ # - 省略datadisk和bandwidth参数无法成功修改,具体用法可参考对应测试样例
222
+ def change_instance_type(iid, itype, duration=nil, datadisk=nil, bandwidth=nil)
223
+ kwargs = {}
224
+ kwargs['InstanceId'] = iid
225
+ kwargs['InstanceType'] = itype
226
+ unless duration.nil?
227
+ /^\d+[HhMm]$/.match(duration) ? kwargs['Duration'] = duration : (raise Exception('Illegal duration format'))
228
+ end
229
+
230
+ kwargs['ExtraExtDisksize'] = datadisk unless datadisk.nil?
231
+ kwargs['ExtraExtBandwidth'] = bandwidth unless bandwidth.nil?
232
+
233
+ self.request('ChangeInstanceType', *kwargs)
234
+ end
235
+
236
+ # 获取虚拟机的metadata
237
+ # - @param [String] iid 虚拟机ID
238
+ # - @return [Hash] 一个hash,包含虚拟机所有metadata的key/value
239
+ def get_instance_metadata(iid)
240
+ kwargs = {}
241
+ kwargs['InstanceId'] = iid
242
+ val = self.request('GetInstanceMetadata', *kwargs)
243
+ val['InstanceMetadata']
244
+ end
245
+
246
+ # 修改虚拟机的metadata
247
+ # - @param [String] iid 虚拟机ID
248
+ # - @param [Hash] data 需要增加或修改的metadata信息
249
+ def put_instance_metadata(iid, data)
250
+ kwargs = {}
251
+ kwargs['InstanceId'] = iid
252
+ names = []
253
+ values = []
254
+ data.each do |key, value|
255
+ names.push(key)
256
+ values.push(value)
257
+ end
258
+ kwargs['Name'] = names
259
+ kwargs['Value'] = values
260
+ self.request('PutInstanceMetadata', *kwargs)
261
+ end
262
+
263
+ # 获取用户的SSH密钥对
264
+ # - @param [Integer] limit 最大返回数量,用于分页控制
265
+ # - @param [Integer] offset 返回偏移量,用于分页控制
266
+ # - @param [Hash] filters 过滤条件,key/value分别指定过滤字段名称和值,支持的字段名称为:name
267
+ # - @return [Hash] 包含SSH密钥对列表
268
+ def describe_key_pairs(limit=0, offset=0, filters=nil)
269
+ kwargs = {}
270
+ self.parse_array_params(limit, offset, filters, kwargs)
271
+ val = self.request('DescribeKeyPairs', *kwargs)
272
+ val['KeyPairSet']
273
+ end
274
+
275
+ # 导入一个用户的SSH公钥,并创建一个SSH密钥对
276
+ # - @param [String] name 密钥对名称
277
+ # - @param [String] pubkey SSH公钥信息
278
+ # - @return [Hash] 创建的SSH密钥对信息
279
+ def import_key_pair(name, pubkey)
280
+ kwargs = {}
281
+ kwargs['KeyName'] = name
282
+ kwargs['PublicKeyMaterial'] = pubkey
283
+ val = self.request('ImportKeyPair', *kwargs)
284
+ val['KeyPair']
285
+ end
286
+
287
+ # 删除一个SSH密钥对
288
+ # - @param [String] kid 密钥对ID
289
+ def delete_key_pair(kid)
290
+ kwargs = {}
291
+ kwargs['KeyName'] = kid
292
+ self.request('DeleteKeyPair', *kwargs)
293
+ end
294
+
295
+ # 保存虚拟机的模板
296
+ # - @param [String] iid 虚拟机ID
297
+ # - @param [String] name 模板名称
298
+ # - @param [String] notes 保存模板的说明
299
+ # - @return [Hash] 请求是否成功
300
+ def create_template(iid, name, notes=nil)
301
+ kwargs = {}
302
+ kwargs['InstanceId'] = iid
303
+ kwargs['Name'] = name
304
+ kwargs['Notes'] = notes unless notes.nil?
305
+ self.request('CreateTemplate', *kwargs)
306
+ end
307
+
308
+ # 删除一个模板
309
+ # - @param [String] tid 模板ID
310
+ def delete_template(tid)
311
+ kwargs = {}
312
+ kwargs['TemplateId'] = tid
313
+ self.request('DeleteTemplate', *kwargs)
314
+ end
315
+ end
@@ -0,0 +1,169 @@
1
+ require "uri"
2
+ require "base64"
3
+ require "openssl"
4
+ require "net/http"
5
+ require "json"
6
+ require "logger"
7
+ require "rubygems"
8
+ require "crack"
9
+ require "erb"
10
+ include ERB::Util
11
+ module MosSdk
12
+ class Base
13
+ end
14
+ end
15
+
16
+ class MosSdk::Base
17
+ attr_accessor :access, :secret, :url, :format, :timeout, :debug
18
+
19
+ # 基类初始化函数
20
+ # - @param [String] access
21
+ # - @param [String] secret
22
+ # - @param [String] url
23
+ # - @param [String] format 默认为xml格式
24
+ # - @param [Integer] timeout
25
+ # - @param [] debug
26
+ def initialize(access, secret, url, format='xml', timeout=300, debug=false)
27
+ @access=access
28
+ @secret=secret
29
+ @url=url
30
+ @format=format
31
+ @timeout=timeout
32
+ @debug=debug
33
+ end
34
+
35
+ def raw_request(action, *kwargs)
36
+ self._request(action, *kwargs)
37
+ end
38
+
39
+ # 处理请求函数
40
+ # - @param [String] action 函数名
41
+ # - @param [Hash] kwargs 函数调用参数
42
+ # - @return [HTTPResponse] 返回请求处理结果
43
+ def _request(action, *kwargs)
44
+ params = {}
45
+ params['Action'] = action
46
+ params['AWSAccessKeyId'] = self.access
47
+ params['Timestamp'] = Time.now.strftime("%Y-%m-%dT%H:%M:%S.000Z")
48
+ params['SignatureVersion'] = '2'
49
+ params['SignatureMethod'] = 'HmacSHA256'
50
+
51
+ unless kwargs.empty?
52
+ kwargs.each do |k, v|
53
+ if v.kind_of?(Array)
54
+ i = 1
55
+ v.each do |vi|
56
+ params['%s.%d' % [k, i]] = vi
57
+ i += 1
58
+ end
59
+ else
60
+ params[k] = v
61
+ end
62
+ end
63
+ end
64
+
65
+ params['Format'] = self.format if self.format
66
+ sig = self.get_signature(params)
67
+ params['Signature'] = sig
68
+ headers = {}
69
+ headers['User-Agent'] = 'ruby-mosclient'
70
+ data = URI.encode_www_form(params)
71
+ puts self.url + '?' + data if self.debug
72
+
73
+ uri = URI.parse(self.url)
74
+ http = Net::HTTP.new(uri.host, uri.port)
75
+ http.use_ssl=true
76
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
77
+ http.request_post('/', data, headers)
78
+ end
79
+
80
+ # 签名函数
81
+ # - @param [Hash] params 签名参数
82
+ # - @return [String] 签名处理结果
83
+ def get_signature(params) #signature method
84
+ req = URI.parse(self.url)
85
+ host = req.host
86
+ endpoint = host + ':' + req.port.to_s
87
+ path = req.path
88
+ path = '/' if req.path == ''
89
+ cred_dict = {'access' => self.access,
90
+ 'host' => endpoint,
91
+ 'verb' => 'POST',
92
+ 'path' => path,
93
+ 'params' => params,
94
+ }
95
+ params=Hash[params.sort]
96
+ sha256_hmac(string_to_sign(cred_dict, params))
97
+ end
98
+
99
+ # 字符串格式化函数
100
+ # - @param [Hash] cred_dict 认证信息
101
+ # - @param [Hash] params 认证参数
102
+ # - @return [String] 格式化结果
103
+ def string_to_sign(cred_dict, params)
104
+ [
105
+ cred_dict['verb'],
106
+ cred_dict['host'],
107
+ cred_dict['path'],
108
+ URI.encode_www_form(params),
109
+ ].join("\n")
110
+ end
111
+
112
+ # sha256算法实现
113
+ # - @param [String] value 加密内容
114
+ # - @return [String] 加密结果
115
+ def sha256_hmac(value)
116
+ Base64.encode64(
117
+ OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), self.secret, value)
118
+ ).strip
119
+ end
120
+
121
+ # 请求/响应函数,核心处理由_request函数实现
122
+ # - @param [String] action 函数名
123
+ # - @param [Hash] kwargs 函数调用参数
124
+ # - @return [Hash] 返回函数调用结果
125
+ def request(action, *kwargs)
126
+ resp = self._request(action, *kwargs)
127
+ body = resp.body
128
+ if self.debug
129
+ puts body
130
+ end
131
+
132
+ # todo begin 中if...else 执行else
133
+ begin
134
+ if resp.header['Content-Type'].start_with?('application/json')
135
+ body = JSON.parse(body)
136
+ else
137
+ body = Crack::XML.parse(body)
138
+ body["#{action}Response"]
139
+ end
140
+ rescue
141
+ return body
142
+ end
143
+ end
144
+
145
+ # 结果格式化函数
146
+ # - @param [Integer] limit 最大返回数量,用于分页控制
147
+ # - @param [Integer] offset 返回偏移量,用于分页控制
148
+ # - @param [Hash] filters 过滤条件,key/value分别指定过滤字段名称和值
149
+ # - @param [Hash] kwargs 其他参数
150
+ def parse_array_params(limit, offset, filters, kwargs)
151
+ kwargs['Limit'] = limit if limit > 0
152
+ kwargs['Offset'] = offset if offset > 0
153
+ unless filters.nil?
154
+ fidx = 1
155
+ filters.each do |k, vs|
156
+ kwargs['Filter.%d.Name' % fidx] = k
157
+ vs = [vs] unless vs.kind_of?(Array)
158
+ vidx = 1
159
+ vs.each do |v|
160
+ kwargs['Filter.%d.Value.%d' % [fidx, vidx]] = v
161
+ vidx += 1
162
+ end
163
+ fidx += 1
164
+ end
165
+ end
166
+ end
167
+
168
+ end
169
+
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mos_sdk
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - yangcs2009
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Ruby SDK for MOS.
42
+ email:
43
+ - yangchangsheng@meituan.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - lib/mos_sdk.rb
49
+ - lib/mos_sdk/base.rb
50
+ homepage: ''
51
+ licenses:
52
+ - MIT
53
+ metadata: {}
54
+ post_install_message:
55
+ rdoc_options: []
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ requirements: []
69
+ rubyforge_project:
70
+ rubygems_version: 2.4.5
71
+ signing_key:
72
+ specification_version: 4
73
+ summary: Ruby SDK for MOS.
74
+ test_files: []