qc.rb 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/README.md +126 -0
- data/bin/qc +36 -7
- data/lib/qc.rb +135 -43
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5dccf331efcb29098e651c3865f5d4d63f019586
|
4
|
+
data.tar.gz: 066553273f56fcbd831063096393b7bced68ce9c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1a25f3e039f696056512a592178509232ade5119662f25eb12f1473d4a1c722d89813cbf809b8f648364ee5f467cf84d5a3c1ecd2269ed14ab443a0700b08077
|
7
|
+
data.tar.gz: 4060d4ae2a012ec7ad54ba05763cd7b0a12812948b31730f929be7cbc6714ee843b607af14e8ed93c659d9751800f5e0d6d9f251088c1b5d3f8db55a25ced1fb
|
data/README.md
CHANGED
@@ -2,3 +2,129 @@ qc.rb
|
|
2
2
|
=====
|
3
3
|
|
4
4
|
QingCloud API Library to handle instances, networks, etc. on QingCloud.com
|
5
|
+
|
6
|
+
### Installation
|
7
|
+
|
8
|
+
You can install *qc.rb* via RubyGems:
|
9
|
+
|
10
|
+
```bash
|
11
|
+
gem install qc.rb
|
12
|
+
```
|
13
|
+
|
14
|
+
### Important Notice
|
15
|
+
|
16
|
+
I'm not a native chinese speaker! Yet the complete documentation of QingCloud.com is in chinese! Due to that it is reasonable to expect that my understanding of the API might not be 100% correct! You are very welcome to improve the code!
|
17
|
+
|
18
|
+
### Usage
|
19
|
+
|
20
|
+
You can use *qc.rb* via *qc* as a CLI or direct as a Ruby library.
|
21
|
+
|
22
|
+
#### SSH
|
23
|
+
|
24
|
+
Get all public keys:
|
25
|
+
|
26
|
+
CLI Version:
|
27
|
+
|
28
|
+
```bash
|
29
|
+
qc ssh describe
|
30
|
+
```
|
31
|
+
|
32
|
+
.rb Version:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
# Each Public Key is available in *s*
|
36
|
+
QC::KeyPair.describe {|s| puts s}
|
37
|
+
```
|
38
|
+
|
39
|
+
#### Instances
|
40
|
+
|
41
|
+
Get all instances:
|
42
|
+
|
43
|
+
CLI Version:
|
44
|
+
|
45
|
+
```bash
|
46
|
+
qc ins describe
|
47
|
+
```
|
48
|
+
|
49
|
+
.rb Version:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
# Each instance is available in *i*
|
53
|
+
QC::Instance.describe {|i| puts i}
|
54
|
+
```
|
55
|
+
|
56
|
+
Create new Instance:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
QC::Instance.run instance_name: 'NameOfInstance', login_keypair: 'kp-sadasd67' # => instance_id
|
60
|
+
```
|
61
|
+
|
62
|
+
Delete Instance:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
i = QC::Instance.load 'i-adssad7'
|
66
|
+
i.terminate! # => {"action"=>"TerminateInstancesResponse", "job_id"=>"j-asd7djk", "ret_code"=>0}
|
67
|
+
```
|
68
|
+
|
69
|
+
Add IP device to Instance:
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
i = QC::Instance.load 'i-adssad7'
|
73
|
+
i.ip = 'eip-sadjkdsa7' # => 'eip-sadjkdsa7'
|
74
|
+
```
|
75
|
+
|
76
|
+
#### IPs
|
77
|
+
|
78
|
+
Get all IPs:
|
79
|
+
|
80
|
+
CLI Version:
|
81
|
+
|
82
|
+
```bash
|
83
|
+
qc ip describe
|
84
|
+
```
|
85
|
+
|
86
|
+
.rb Version:
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
# Each IP is available in *i*
|
90
|
+
QC::Eip.describe {|i| puts i}
|
91
|
+
```
|
92
|
+
|
93
|
+
Allocate new IP:
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
# Create IP width bandwidth 3MB
|
97
|
+
Eip.allocate bandwidth: 3 # => eip_id
|
98
|
+
```
|
99
|
+
|
100
|
+
Release IP:
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
# Release IP with ID 'eip-12djpg8q'
|
104
|
+
Eip.load('eip-12djpg8q').release! # => true | false
|
105
|
+
```
|
106
|
+
|
107
|
+
Change Bandwidth:
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
# Change bandwidth of IP with ID 'eip-12djpg8q' to 2MB
|
111
|
+
ip = Eip.load('eip-12djpg8q')
|
112
|
+
ip.bandwidth = 2 # => 2
|
113
|
+
```
|
114
|
+
|
115
|
+
#### Volumes
|
116
|
+
|
117
|
+
Get all Volumes:
|
118
|
+
|
119
|
+
CLI Version:
|
120
|
+
|
121
|
+
```bash
|
122
|
+
qc vol describe
|
123
|
+
```
|
124
|
+
|
125
|
+
.rb Version:
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
# Each Volume is available in *v*
|
129
|
+
QC::Volume.describe {|v| puts v}
|
130
|
+
```
|
data/bin/qc
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
3
|
+
require "#{File.dirname(__FILE__)}/../lib/qc.rb"
|
4
4
|
|
5
5
|
def help_header cmd, options
|
6
6
|
<<HEADER
|
@@ -16,24 +16,53 @@ HEADER
|
|
16
16
|
end
|
17
17
|
|
18
18
|
case ARGV[0]
|
19
|
+
when 'vol'
|
20
|
+
case ARGV[1]
|
21
|
+
when 'describe'
|
22
|
+
QC::Volume.describe {|v| puts v}
|
23
|
+
else
|
24
|
+
puts help_header('vol [option]', <<HELP)
|
25
|
+
describe List all volumes
|
26
|
+
HELP
|
27
|
+
end
|
19
28
|
when 'ssh'
|
20
29
|
case ARGV[1]
|
21
|
-
when '
|
22
|
-
QC::
|
30
|
+
when 'describe'
|
31
|
+
QC::KeyPair.describe {|s| puts s}
|
23
32
|
else
|
24
33
|
puts help_header('ssh [option]', <<HELP)
|
25
|
-
|
34
|
+
describe List all public keys
|
26
35
|
HELP
|
27
36
|
end
|
28
37
|
when 'ins'
|
29
38
|
case ARGV[1]
|
30
|
-
when '
|
31
|
-
QC::Instance.
|
39
|
+
when 'describe'
|
40
|
+
QC::Instance.describe {|i| puts i}
|
32
41
|
else
|
33
42
|
puts help_header('ins [option]', <<HELP)
|
34
|
-
|
43
|
+
describe List all machines
|
44
|
+
HELP
|
45
|
+
end
|
46
|
+
when 'ip'
|
47
|
+
case ARGV[1]
|
48
|
+
when 'describe'
|
49
|
+
QC::Eip.describe {|s| puts s}
|
50
|
+
else
|
51
|
+
puts help_header('ip [option]', <<HELP)
|
52
|
+
describe List all IPs
|
35
53
|
HELP
|
36
54
|
end
|
55
|
+
|
56
|
+
when 'img'
|
57
|
+
case ARGV[1]
|
58
|
+
when 'describe'
|
59
|
+
QC::Image.describe.sort.each {|s| puts s}
|
60
|
+
else
|
61
|
+
puts help_header('img [option]', <<HELP)
|
62
|
+
describe List all Images
|
63
|
+
HELP
|
64
|
+
end
|
65
|
+
|
37
66
|
else
|
38
67
|
puts help_header('[option]', <<HELP)
|
39
68
|
ssh SSH Key Management
|
data/lib/qc.rb
CHANGED
@@ -7,7 +7,7 @@ require 'yaml'
|
|
7
7
|
require 'fileutils'
|
8
8
|
|
9
9
|
module QC
|
10
|
-
VERSION = '0.0.
|
10
|
+
VERSION = '0.0.2'
|
11
11
|
|
12
12
|
def QC.load_config key
|
13
13
|
f = File.expand_path('~/.qingcloud/config.yaml')
|
@@ -56,58 +56,135 @@ module QC
|
|
56
56
|
url_b64_hmac = CGI.escape(b64_hmac)
|
57
57
|
end
|
58
58
|
|
59
|
-
class
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
@
|
66
|
-
@key = s['pub_key']
|
59
|
+
class DataType
|
60
|
+
attr_reader :result
|
61
|
+
|
62
|
+
@identifier = 'NOT_IMPLEMENTED'
|
63
|
+
|
64
|
+
def initialize h
|
65
|
+
@values = h
|
67
66
|
end
|
68
67
|
|
69
68
|
def to_s
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
"
|
78
|
-
|
69
|
+
@values.to_yaml
|
70
|
+
end
|
71
|
+
|
72
|
+
def method_missing met
|
73
|
+
if @values.has_key? met.to_s
|
74
|
+
@values[met.to_s]
|
75
|
+
else
|
76
|
+
raise NoMethodError.new "undefined method `#{met}'"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.describe p = {}, &block
|
81
|
+
req = QC::API::Request.new "Describe#{@identifier}s", p
|
82
|
+
@result = req.execute!(QC::Key)
|
83
|
+
if block_given?
|
84
|
+
@result["#{@identifier.downcase}_set"].to_a.each {|s| block.call(self.new(s))}
|
85
|
+
else
|
86
|
+
@result["#{@identifier.downcase}_set"].to_a.map {|s| self.new(s)}
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class KeyPair < DataType
|
92
|
+
@identifier = 'KeyPair'
|
93
|
+
end
|
94
|
+
|
95
|
+
class Instance < DataType
|
96
|
+
@identifier = 'Instance'
|
97
|
+
|
98
|
+
def Instance.run p = {image_id: 'precisex64a', instance_name: nil, count: 1, login_mode: 'keypair',
|
99
|
+
login_keypair: nil, login_passwd: nil, security_group: nil, zone: nil, instance_type: 'small_b'}
|
100
|
+
p[:image_id] = 'precisex64a' if p[:image_id].nil?
|
101
|
+
p[:login_mode] = 'keypair' if p[:login_mode].nil?
|
102
|
+
p[:instance_type] = 'small_b' if p[:instance_type].nil?
|
103
|
+
p['vxnets.1'] = 'vxnet-0' if p['vxnets.1'].nil?
|
104
|
+
ret = API::Request.execute! 'RunInstances', p
|
105
|
+
ret['instances']
|
106
|
+
end
|
107
|
+
|
108
|
+
def Instance.load instance_id
|
109
|
+
Instance.describe('instances.1' => instance_id)[0]
|
110
|
+
end
|
111
|
+
|
112
|
+
def terminate!
|
113
|
+
p = {'instances.1' => @values['instance_id']}
|
114
|
+
API::Request.execute!('TerminateInstances', p)
|
115
|
+
end
|
116
|
+
|
117
|
+
def ip= eip_id
|
118
|
+
p = {'instance' => @values['instance_id'], 'eip' => eip_id}
|
119
|
+
API::Request.execute!('AssociateEip', p)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
class Volume < DataType
|
124
|
+
@identifier = 'Volume'
|
125
|
+
end
|
126
|
+
|
127
|
+
class Eip < DataType
|
128
|
+
@identifier = 'Eip'
|
129
|
+
|
130
|
+
def Eip.allocate p = {bandwidth: 1, eip_name: nil, count: 1, need_icp: nil, zone: nil}
|
131
|
+
ret = API::Request.execute! 'AllocateEips', p
|
132
|
+
if ret.respond_to? :has_key?
|
133
|
+
ret['eips']
|
134
|
+
else
|
135
|
+
false
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def Eip.release eips: [], zone: nil
|
140
|
+
if eips.size > 0
|
141
|
+
p = {}
|
142
|
+
1.upto(eips.size).each { |i| p["eips.#{i}"] = eips[i-1] }
|
143
|
+
p[:zone] = zone
|
144
|
+
API::Request.execute!('ReleaseEips', p)
|
145
|
+
else
|
146
|
+
false
|
147
|
+
end
|
79
148
|
end
|
80
149
|
|
81
|
-
def
|
82
|
-
|
83
|
-
|
150
|
+
def Eip.load eip_id
|
151
|
+
Eip.describe('eips.1' => eip_id)[0]
|
152
|
+
end
|
153
|
+
|
154
|
+
def bandwidth= b
|
155
|
+
p = {'eips.1' => @values['eip_id'], 'bandwidth' => b}
|
156
|
+
ret = API::Request.execute!('ChangeEipsBandwidth', p)
|
157
|
+
if ret.respond_to? :has_key?
|
158
|
+
b
|
159
|
+
else
|
160
|
+
false
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def release!
|
165
|
+
p = {'eips.1' => @values['eip_id']}
|
166
|
+
API::Request.execute!('ReleaseEips', p)
|
84
167
|
end
|
85
168
|
end
|
86
169
|
|
87
|
-
class
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
170
|
+
class Image < DataType
|
171
|
+
include Comparable
|
172
|
+
@identifier = 'Image'
|
173
|
+
|
174
|
+
def Image.describe p = {}, &block
|
175
|
+
_p = p.dup
|
176
|
+
unless _p.has_key? 'provider'
|
177
|
+
_p['provider'] = 'system'
|
178
|
+
end
|
179
|
+
super _p, &block
|
95
180
|
end
|
96
181
|
|
97
182
|
def to_s
|
98
|
-
|
99
|
-
ID: "#{@id}"
|
100
|
-
Name: "#{@name}"
|
101
|
-
Type: "#{@type}"
|
102
|
-
VCPU: "#{@vcpu}"
|
103
|
-
Description: "#{@desc}"
|
104
|
-
Status: "#{@status}"
|
105
|
-
STR
|
183
|
+
[@values['image_id'], @values['image_name']].to_yaml
|
106
184
|
end
|
107
185
|
|
108
|
-
def
|
109
|
-
|
110
|
-
r.execute!(QC::Key)['instance_set'].to_a.each {|s| block.call(Instance.new(s))}
|
186
|
+
def <=> o
|
187
|
+
@values['image_id'] <=> o.image_id
|
111
188
|
end
|
112
189
|
end
|
113
190
|
|
@@ -115,7 +192,17 @@ STR
|
|
115
192
|
class Request
|
116
193
|
attr_reader :response
|
117
194
|
|
118
|
-
def
|
195
|
+
def Request.execute! a, p = {}
|
196
|
+
req = QC::API::Request.new a, p
|
197
|
+
@result = req.execute!(QC::Key)
|
198
|
+
if @result['ret_code'] == 0
|
199
|
+
@result
|
200
|
+
else
|
201
|
+
raise ArgumentError.new("#{@result['ret_code']}: #{@result['message']}")
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def initialize action, extra_params = {}
|
119
206
|
@response = :not_requested
|
120
207
|
|
121
208
|
@params = []
|
@@ -123,8 +210,13 @@ STR
|
|
123
210
|
@params << ['access_key_id', QC::AccessKeyId]
|
124
211
|
@params << ['signature_method', 'HmacSHA256']
|
125
212
|
@params << ['signature_version', 1]
|
126
|
-
|
127
|
-
extra_params.
|
213
|
+
zone_set = false
|
214
|
+
extra_params.each_pair do |k,v|
|
215
|
+
zone_set = true if k == 'zone'
|
216
|
+
next if v.nil?
|
217
|
+
@params << [k.to_s, v]
|
218
|
+
end
|
219
|
+
@params << ['zone', QC::Zone] unless zone_set
|
128
220
|
end
|
129
221
|
|
130
222
|
def execute!(key)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: qc.rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Bovensiepen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-02-
|
11
|
+
date: 2014-02-16 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: QingCloud API Library to handle instances, networks, internetconnections,
|
14
14
|
etc. on QingCloud.com
|