openstack_activeresource 0.1.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.
- data/.document +5 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +49 -0
- data/LICENSE.txt +14 -0
- data/README.rdoc +427 -0
- data/Rakefile +44 -0
- data/VERSION +1 -0
- data/lib/hot_fixes.rb +55 -0
- data/lib/locales/en.yml +5 -0
- data/lib/open_stack/base.rb +88 -0
- data/lib/open_stack/common.rb +56 -0
- data/lib/open_stack/glance/base.rb +39 -0
- data/lib/open_stack/glance/image.rb +33 -0
- data/lib/open_stack/glance.rb +27 -0
- data/lib/open_stack/keystone/admin/base.rb +41 -0
- data/lib/open_stack/keystone/admin/role.rb +35 -0
- data/lib/open_stack/keystone/admin/tenant.rb +104 -0
- data/lib/open_stack/keystone/admin/user.rb +98 -0
- data/lib/open_stack/keystone/admin/user_role.rb +34 -0
- data/lib/open_stack/keystone/admin.rb +32 -0
- data/lib/open_stack/keystone/public/auth.rb +141 -0
- data/lib/open_stack/keystone/public/base.rb +41 -0
- data/lib/open_stack/keystone/public/tenant.rb +64 -0
- data/lib/open_stack/keystone/public.rb +31 -0
- data/lib/open_stack/keystone.rb +27 -0
- data/lib/open_stack/nova/compute/base.rb +41 -0
- data/lib/open_stack/nova/compute/base_detail.rb +59 -0
- data/lib/open_stack/nova/compute/flavor.rb +56 -0
- data/lib/open_stack/nova/compute/floating_ip.rb +61 -0
- data/lib/open_stack/nova/compute/floating_ip_pool.rb +36 -0
- data/lib/open_stack/nova/compute/image.rb +76 -0
- data/lib/open_stack/nova/compute/key_pair.rb +47 -0
- data/lib/open_stack/nova/compute/network.rb +45 -0
- data/lib/open_stack/nova/compute/security_group.rb +117 -0
- data/lib/open_stack/nova/compute/server.rb +313 -0
- data/lib/open_stack/nova/compute/simple_tenant_usage.rb +128 -0
- data/lib/open_stack/nova/compute/volume_attachment.rb +98 -0
- data/lib/open_stack/nova/compute.rb +39 -0
- data/lib/open_stack/nova/volume/base.rb +41 -0
- data/lib/open_stack/nova/volume/volume.rb +77 -0
- data/lib/open_stack/nova/volume.rb +29 -0
- data/lib/open_stack/nova.rb +27 -0
- data/lib/open_stack.rb +40 -0
- data/lib/openstack_activeresource.rb +1 -0
- data/test/helper.rb +18 -0
- data/test/test_openstack-activeresource.rb +7 -0
- metadata +190 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
# This file is part of the OpenStack-ActiveResource
|
2
|
+
#
|
3
|
+
# Copyright (C) 2012 Unidata S.p.A. (Davide Guerri - d.guerri@unidata.it)
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
module OpenStack
|
19
|
+
module Nova
|
20
|
+
module Compute
|
21
|
+
|
22
|
+
class Network < Base
|
23
|
+
self.collection_name = "os-networks"
|
24
|
+
|
25
|
+
schema do
|
26
|
+
attribute :bridge, :string
|
27
|
+
attribute :bridge_interface, :string
|
28
|
+
attribute :cidr, :string
|
29
|
+
attribute :label, :string
|
30
|
+
attribute :multi_host, :boolean
|
31
|
+
attribute :vlan, :integer
|
32
|
+
attribute :project_id, :string
|
33
|
+
end
|
34
|
+
|
35
|
+
validates :bridge, :format => {:with => /\A[a-z][a-z0-9]{1,8}\Z/i}
|
36
|
+
validates :bridge_interface, :format => {:with => /\A[a-z]{1,5}[a-z0-9]{1,5}(\.[0-9]{1,4})?\Z/i}
|
37
|
+
validates :cidr, :presence => true
|
38
|
+
validates :label, :presence => true, :format => {:with => /\A[\w\s\d]{1,20}\Z/i}
|
39
|
+
validates :vlan, :presence => true, :numericality => {:greater_than_or_equal_to => 2, :less_than_or_equal_to => 4096}
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# This file is part of the OpenStack-ActiveResource
|
2
|
+
#
|
3
|
+
# Copyright (C) 2012 Unidata S.p.A. (Davide Guerri - d.guerri@unidata.it)
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
module OpenStack
|
19
|
+
module Nova
|
20
|
+
module Compute
|
21
|
+
|
22
|
+
class SecurityGroup < Base
|
23
|
+
self.element_name = "os-security-group"
|
24
|
+
self.collection_name = "os-security-groups"
|
25
|
+
|
26
|
+
schema do
|
27
|
+
attribute :tenant_id, :string
|
28
|
+
attribute :name, :string
|
29
|
+
attribute :description, :string
|
30
|
+
end
|
31
|
+
|
32
|
+
validates :name, :presence => true
|
33
|
+
validates :description, :presence => true
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
class SecurityGroup::Rule < Base
|
38
|
+
self.element_name = "os-security-group-rule"
|
39
|
+
self.collection_name = "os-security-group-rules"
|
40
|
+
|
41
|
+
schema do
|
42
|
+
attribute :ip_protocol, :string
|
43
|
+
attribute :from_port, :integer
|
44
|
+
attribute :to_port, :integer
|
45
|
+
attribute :parent_group_id, :string
|
46
|
+
attribute :cidr, :string
|
47
|
+
end
|
48
|
+
|
49
|
+
validates :ip_protocol, :presence => true, :inclusion => {:in => %w(tcp udp icmp)}
|
50
|
+
validates :cidr, :presence => true, :format => {:with => OpenStack::IPV4_CIDR_REGEX}
|
51
|
+
validates :parent_group_id, :presence => true
|
52
|
+
validates :from_port, :presence => true, :numericality => {:only_integer => true}
|
53
|
+
validates :to_port, :presence => true, :numericality => {:only_integer => true}
|
54
|
+
|
55
|
+
validates_numericality_of :from_port, :less_than_or_equal_to => 255, :greater_than_or_equal_to => -1, :if => Proc.new { |rule| rule.icmp? }
|
56
|
+
validates_numericality_of :from_port, :less_than_or_equal_to => 65535, :greater_than_or_equal_to => 1, :if => Proc.new { |rule| rule.udp? or rule.tcp? }
|
57
|
+
|
58
|
+
validates_numericality_of :to_port, :less_than_or_equal_to => 255, :greater_than_or_equal_to => -1, :if => Proc.new { |rule| rule.icmp? }
|
59
|
+
validates_numericality_of :to_port, :less_than_or_equal_to => 65535, :greater_than_or_equal_to => 1, :if => Proc.new { |rule| rule.udp? or rule.tcp? }
|
60
|
+
validates_numericality_of :to_port, :greater_than_or_equal_to => :from_port, :if => Proc.new { |rule| rule.udp? or rule.tcp? }
|
61
|
+
|
62
|
+
|
63
|
+
def initialize(attributes = {}, persisted = false)
|
64
|
+
attributes = attributes.with_indifferent_access
|
65
|
+
new_attributes = {
|
66
|
+
:id => attributes[:id],
|
67
|
+
:ip_protocol => attributes[:ip_protocol],
|
68
|
+
:from_port => attributes[:from_port],
|
69
|
+
:to_port => attributes[:to_port],
|
70
|
+
:cidr => attributes[:cidr] || attributes[:ip_range][:cidr],
|
71
|
+
:parent_group_id => attributes[:parent_group].present? ? attributes[:parent_group].id : nil
|
72
|
+
}
|
73
|
+
super(new_attributes, persisted)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Overload ActiveRecord::encode method
|
77
|
+
# Custom encoding to deal with openstack API
|
78
|
+
def encode(options={})
|
79
|
+
to_encode = {
|
80
|
+
:security_group_rule => {
|
81
|
+
:ip_protocol => ip_protocol,
|
82
|
+
:from_port => from_port,
|
83
|
+
:to_port => to_port,
|
84
|
+
:cidr => cidr,
|
85
|
+
:parent_group_id => parent_group_id,
|
86
|
+
}
|
87
|
+
}
|
88
|
+
to_encode.send("to_#{self.class.format.extension}", options)
|
89
|
+
end
|
90
|
+
|
91
|
+
def parent_group=(group)
|
92
|
+
parent_group_id = group.id
|
93
|
+
end
|
94
|
+
|
95
|
+
def parent_group
|
96
|
+
return nil if parent_group_id.nil?
|
97
|
+
SecurityGroup.find(parent_group_id)
|
98
|
+
end
|
99
|
+
|
100
|
+
def icmp?
|
101
|
+
ip_protocol == 'icmp'
|
102
|
+
end
|
103
|
+
|
104
|
+
def udp?
|
105
|
+
ip_protocol == 'udp'
|
106
|
+
end
|
107
|
+
|
108
|
+
def tcp?
|
109
|
+
ip_protocol == 'tcp'
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
@@ -0,0 +1,313 @@
|
|
1
|
+
# This file is part of the OpenStack-ActiveResource
|
2
|
+
#
|
3
|
+
# Copyright (C) 2012 Unidata S.p.A. (Davide Guerri - d.guerri@unidata.it)
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
module OpenStack
|
19
|
+
module Nova
|
20
|
+
module Compute
|
21
|
+
|
22
|
+
class Server < BaseDetail
|
23
|
+
|
24
|
+
schema do
|
25
|
+
attribute :name, :string
|
26
|
+
attribute :status, :string
|
27
|
+
attribute :updated_at, :datetime
|
28
|
+
attribute :created_at, :datetime
|
29
|
+
attribute :vm_state, :string
|
30
|
+
attribute :task, :string
|
31
|
+
attribute :power_state, :integer
|
32
|
+
attribute :host_id, :string
|
33
|
+
attribute :tenant_id, :string
|
34
|
+
attribute :user_id, :string
|
35
|
+
attribute :image_id, :string
|
36
|
+
attribute :flavor_id, :string
|
37
|
+
attribute :key_pair_id, :string
|
38
|
+
end
|
39
|
+
|
40
|
+
validates :name, :format => {:with => /\A[\w\.\-\_]{2,}\Z/}, :length => {:maximum => 255}
|
41
|
+
validates :image, :presence => true
|
42
|
+
validates :flavor, :presence => true
|
43
|
+
|
44
|
+
def self.all_by_tenant(tenant)
|
45
|
+
tenant_id = tenant.is_a?(OpenStack::Keystone::Admin::Tenant) ? tenant.id : tenant
|
46
|
+
|
47
|
+
find(:all, :params => {:tenant_id => tenant_id})
|
48
|
+
end
|
49
|
+
|
50
|
+
def initialize(attributes = {}, persisted = false)
|
51
|
+
attributes = attributes.with_indifferent_access
|
52
|
+
new_attributes = {
|
53
|
+
:id => attributes[:id],
|
54
|
+
:name => attributes[:name],
|
55
|
+
:status => attributes[:status],
|
56
|
+
:updated_at => attributes[:updated].present? ? DateTime.strptime(attributes[:updated], OpenStack::DATETIME_FORMAT) : nil,
|
57
|
+
:created_at => attributes[:created].present? ? DateTime.strptime(attributes[:created], OpenStack::DATETIME_FORMAT) : nil,
|
58
|
+
:vm_state => attributes[:'OS-EXT-STS:vm_state'],
|
59
|
+
:task => attributes[:'OS-EXT-STS:task_state'],
|
60
|
+
:power_state => attributes['OS-EXT-STS:power_state'],
|
61
|
+
:host_id => attributes[:hostId],
|
62
|
+
:user_data => attributes[:user_data],
|
63
|
+
# :tenant_id => attributes[:tenant_id],
|
64
|
+
# :user_id => attributes[:user_id],
|
65
|
+
:addresses => attributes[:addresses] || []
|
66
|
+
}
|
67
|
+
|
68
|
+
if attributes[:key_pair].present?
|
69
|
+
new_attributes[:key_pair_id] = attributes[:key_pair].name
|
70
|
+
else
|
71
|
+
new_attributes[:key_pair_id] = attributes[:key_name]
|
72
|
+
end
|
73
|
+
|
74
|
+
if attributes[:image].present?
|
75
|
+
new_attributes[:image_id] = attributes[:image].is_a?(Image) ? attributes[:image].id : attributes[:image][:id]
|
76
|
+
elsif attributes[:image_id].present?
|
77
|
+
new_attributes[:image_id] = attributes[:image_id]
|
78
|
+
end
|
79
|
+
|
80
|
+
if attributes[:flavor].present?
|
81
|
+
new_attributes[:flavor_id] = attributes[:flavor].is_a?(Flavor) ? attributes[:flavor].id : attributes[:flavor][:id]
|
82
|
+
elsif attributes[:flavor_id].present?
|
83
|
+
new_attributes[:flavor_id] = attributes[:flavor_id]
|
84
|
+
end
|
85
|
+
|
86
|
+
super(new_attributes, persisted)
|
87
|
+
|
88
|
+
@attributes[:security_group_ids] = get_security_group_ids(attributes[:security_groups])
|
89
|
+
|
90
|
+
self
|
91
|
+
end
|
92
|
+
|
93
|
+
# Overload ActiveRecord::encode method
|
94
|
+
# Custom encoding to deal with openstack API
|
95
|
+
def encode(options={})
|
96
|
+
to_encode = {
|
97
|
+
:server => {
|
98
|
+
:name => name,
|
99
|
+
:imageRef => image_id,
|
100
|
+
:flavorRef => flavor_id,
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
104
|
+
# Optional attributes (openstack will not accept empty attribute for update/create)
|
105
|
+
to_encode[:server][:user_data] = Base64.encode64(user_data) if user_data.present?
|
106
|
+
to_encode[:server][:key_name] = key_pair_id if key_pair_id.present?
|
107
|
+
to_encode[:server][:security_groups] = get_security_groups.map { |sg| {:name => sg.name} } || []
|
108
|
+
|
109
|
+
to_encode.send("to_#{self.class.format.extension}", options)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Accessors
|
113
|
+
|
114
|
+
def image
|
115
|
+
Image.find(image_id) if image_id.present?
|
116
|
+
end
|
117
|
+
|
118
|
+
def image=(image)
|
119
|
+
self.image_id = image.id
|
120
|
+
end
|
121
|
+
|
122
|
+
def flavor
|
123
|
+
Flavor.find(flavor_id) if flavor_id.present?
|
124
|
+
end
|
125
|
+
|
126
|
+
def flavor=(flavor)
|
127
|
+
self.flavor_id = flavor.id
|
128
|
+
end
|
129
|
+
|
130
|
+
def key_pair
|
131
|
+
KeyPair.find(key_pair_id) if key_pair_id.present?
|
132
|
+
end
|
133
|
+
|
134
|
+
def key_pair=(key_pair)
|
135
|
+
self.key_pair_id = key_pair.name
|
136
|
+
end
|
137
|
+
|
138
|
+
def security_groups
|
139
|
+
get_security_groups
|
140
|
+
end
|
141
|
+
|
142
|
+
def security_groups=(security_groups)
|
143
|
+
return if persisted? # Do Nothing (it's a read-only attribute for OpenStack)
|
144
|
+
|
145
|
+
@attributes[:security_group_ids] = get_security_group_ids(security_groups)
|
146
|
+
end
|
147
|
+
|
148
|
+
def addresses
|
149
|
+
addresses = {}
|
150
|
+
if persisted?
|
151
|
+
response = get('ips')
|
152
|
+
response.each { |net, address|
|
153
|
+
addresses[net] = address
|
154
|
+
}
|
155
|
+
else
|
156
|
+
attributes[:addresses]
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def addresses=(something)
|
161
|
+
# Do Nothing (it's a read-only attribute for OpenStack)
|
162
|
+
end
|
163
|
+
|
164
|
+
def volume_attachments(scope = :all)
|
165
|
+
VolumeAttachment.find(scope, :params => {:server_id => self.id})
|
166
|
+
end
|
167
|
+
|
168
|
+
# Misc...
|
169
|
+
|
170
|
+
# Return the list of attached volumes
|
171
|
+
def attached_volumes
|
172
|
+
volume_attachments.present? ? volume_attachments.map { |va| va.volume } : []
|
173
|
+
end
|
174
|
+
|
175
|
+
# Attach a volume
|
176
|
+
def attach_volume!(volume, device_name)
|
177
|
+
VolumeAttachment.create(:volume => volume, :device => device_name, :server => self)
|
178
|
+
end
|
179
|
+
|
180
|
+
# Refresh server status
|
181
|
+
def refresh_status!
|
182
|
+
updated = Server.find(self.id)
|
183
|
+
self.progress = updated.progress
|
184
|
+
self.status = updated.status
|
185
|
+
self.task = updated.task
|
186
|
+
|
187
|
+
self
|
188
|
+
end
|
189
|
+
|
190
|
+
SERVER_STATUSES = {
|
191
|
+
:ACTIVE => I18n.t(:active),
|
192
|
+
:BUILD => I18n.t(:builing),
|
193
|
+
:DELETED => I18n.t(:deleted),
|
194
|
+
:ERROR => I18n.t(:in_error),
|
195
|
+
:HARD_REBOOT => I18n.t(:hard_rebooting),
|
196
|
+
:PASSWORD => I18n.t(:resetting_password),
|
197
|
+
:REBOOT => I18n.t(:soft_rebooting),
|
198
|
+
:REBUILD => I18n.t(:rebuilding_from_image),
|
199
|
+
:RESCUE => I18n.t(:in_rescue_mode),
|
200
|
+
:RESIZE => I18n.t(:resizing),
|
201
|
+
:REVERT_RESIZE => I18n.t(:revert_resizing),
|
202
|
+
:SHUTOFF => I18n.t(:user_powered_down),
|
203
|
+
:SUSPENDED => I18n.t(:suspended),
|
204
|
+
:PAUSED => I18n.t(:paused),
|
205
|
+
:UNKNOWN => I18n.t(:unknown),
|
206
|
+
:VERIFY_RESIZE => I18n.t(:awaiting_verification)
|
207
|
+
}.with_indifferent_access
|
208
|
+
|
209
|
+
# Returns an extended description for the server status
|
210
|
+
def status_description
|
211
|
+
SERVER_STATUSES[status]
|
212
|
+
end
|
213
|
+
|
214
|
+
## Actions
|
215
|
+
|
216
|
+
# Assign a floating IP to the server.
|
217
|
+
# Params:
|
218
|
+
# +floating_ip+:: a FloatingIP to be attached to the server.
|
219
|
+
def add_floating_ip(floating_ip)
|
220
|
+
post(:action, {}, {:addFloatingIp => {:address => floating_ip.ip}}.to_json)
|
221
|
+
end
|
222
|
+
|
223
|
+
# Reboot the server.
|
224
|
+
# Params:
|
225
|
+
# +type+:: type of reboot. Should be 'hard' or 'soft' (defaults to 'hard', may be nil)
|
226
|
+
def reboot(type=:hard)
|
227
|
+
post(:action, {}, {:reboot => {:type => type}}.to_json)
|
228
|
+
end
|
229
|
+
|
230
|
+
# Creates a new snapshot of server.
|
231
|
+
# Params:
|
232
|
+
# +name+:: name of the new snapshot image
|
233
|
+
# +metadata+:: hash of metadata (may be nil)
|
234
|
+
def create_new_image(name, metadata={})
|
235
|
+
post(:action, {}, {:createImage => {:name => name, :metadata => metadata}}.to_json)
|
236
|
+
end
|
237
|
+
|
238
|
+
# Gets the output from the console log for a server.
|
239
|
+
# Params:
|
240
|
+
# +length+:: numbers of lines to get (defaults to 50, may be nil)
|
241
|
+
def console_output(length=50)
|
242
|
+
response = post(:action, {}, {:'os-getConsoleOutput' => {:length => length}}.to_json)
|
243
|
+
|
244
|
+
ActiveSupport::JSON.decode(response.body)['output']
|
245
|
+
end
|
246
|
+
|
247
|
+
# Accesses a VNC console for a specific server.
|
248
|
+
# Params:
|
249
|
+
# +length+:: numbers of lines to get (defaults to 50, may be nil)
|
250
|
+
def vnc_console(type='novnc')
|
251
|
+
response = post(:action, {}, {:'os-getVNCConsole' => {:type => type}}.to_json)
|
252
|
+
|
253
|
+
ActiveSupport::JSON.decode(response.body)['console']['url']
|
254
|
+
end
|
255
|
+
|
256
|
+
# Halts a running server. Changes status to STOPPED.
|
257
|
+
def stop
|
258
|
+
post(:action, {}, {:'os-stop' => nil}.to_json)
|
259
|
+
end
|
260
|
+
|
261
|
+
# Returns a STOPPED server to ACTIVE status.
|
262
|
+
def start
|
263
|
+
post(:action, {}, {:'os-start' => nil}.to_json)
|
264
|
+
end
|
265
|
+
|
266
|
+
# PAUSE a server.
|
267
|
+
def pause
|
268
|
+
post(:action, {}, {:'pause' => nil}.to_json)
|
269
|
+
end
|
270
|
+
|
271
|
+
# Returns a PAUSED server to ACTIVE status.
|
272
|
+
def unpause
|
273
|
+
post(:action, {}, {:'unpause' => nil}.to_json)
|
274
|
+
end
|
275
|
+
|
276
|
+
# Suspend a running server. Changes status to SUSPENDED.
|
277
|
+
def suspend
|
278
|
+
post(:action, {}, {:'suspend' => nil}.to_json)
|
279
|
+
end
|
280
|
+
|
281
|
+
# Resume a SUSPENDED server.
|
282
|
+
def resume
|
283
|
+
post(:action, {}, {:'resume' => nil}.to_json)
|
284
|
+
end
|
285
|
+
|
286
|
+
private
|
287
|
+
|
288
|
+
def get_security_groups
|
289
|
+
security_group_ids.map { |sg_id|
|
290
|
+
SecurityGroup.find sg_id
|
291
|
+
}
|
292
|
+
end
|
293
|
+
|
294
|
+
def get_security_group_ids(security_groups=nil)
|
295
|
+
if security_groups.nil?
|
296
|
+
if persisted?
|
297
|
+
|
298
|
+
get('os-security-groups').map { |security_group| security_group.with_indifferent_access[:id] }
|
299
|
+
else
|
300
|
+
|
301
|
+
[]
|
302
|
+
end
|
303
|
+
else
|
304
|
+
|
305
|
+
security_groups.map { |security_group| security_group.id }
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
end
|
310
|
+
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# This file is part of the OpenStack-ActiveResource
|
2
|
+
#
|
3
|
+
# Copyright (C) 2012 Unidata S.p.A. (Davide Guerri - d.guerri@unidata.it)
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
module OpenStack
|
19
|
+
module Nova
|
20
|
+
module Compute
|
21
|
+
|
22
|
+
class SimpleTenantUsage < Base
|
23
|
+
self.element_name = "os-simple-tenant-usage"
|
24
|
+
self.collection_name = "os-simple-tenant-usage"
|
25
|
+
|
26
|
+
schema do
|
27
|
+
attribute :total_hours, :float
|
28
|
+
attribute :total_vcpus_usage, :float
|
29
|
+
attribute :total_memory_mb_usage, :float
|
30
|
+
attribute :total_local_gb_usage, :float
|
31
|
+
attribute :stop, :datetime
|
32
|
+
attribute :start, :datetime
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.find(*arguments)
|
36
|
+
scope = arguments.slice!(0)
|
37
|
+
options = arguments.slice!(0) || {}
|
38
|
+
|
39
|
+
# Add "detailed => 1" to the query_options because of broken RESTful
|
40
|
+
# (see: http://api.openstack.org @"Simple Usage") - DG - 09/07/2012
|
41
|
+
if options[:params].nil?
|
42
|
+
options[:params] = {:detailed => 1}
|
43
|
+
else
|
44
|
+
options[:params].merge! :detailed => 1
|
45
|
+
end
|
46
|
+
|
47
|
+
# If there is no data for the given date intervals, an empty usage will be returned.
|
48
|
+
# we "filter out" these entries
|
49
|
+
case scope
|
50
|
+
when :all then
|
51
|
+
find_every(options).select { |su| su.attributes[:tenant_id].present? }
|
52
|
+
when :first then
|
53
|
+
su = find_every(options).first
|
54
|
+
su && su.attributes[:tenant_id].present? ? su : nil
|
55
|
+
when :last then
|
56
|
+
su = find_every(options).last
|
57
|
+
su && su.attributes[:tenant_id].present? ? su : nil
|
58
|
+
when :one then
|
59
|
+
su = find_one(options)
|
60
|
+
su && su.attributes[:tenant_id].present? ? su : nil
|
61
|
+
else
|
62
|
+
su = find_single(scope, options)
|
63
|
+
su && su.attributes[:tenant_id].present? ? su : nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def server_usages
|
68
|
+
@attributes[:server_usages].present? ? @attributes[:server_usages] : []
|
69
|
+
end
|
70
|
+
|
71
|
+
def start
|
72
|
+
DateTime.parse(@attributes[:start] + ' UTC')
|
73
|
+
end
|
74
|
+
|
75
|
+
def stop
|
76
|
+
DateTime.parse(@attributes[:stop] + ' UTC')
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.find_from_date(scope, from_date)
|
80
|
+
now = Time.now.utc
|
81
|
+
|
82
|
+
find(scope, :params => {
|
83
|
+
:start => from_date.utc.strftime(OpenStack::DATETIME_FORMAT),
|
84
|
+
:end => now.strftime(OpenStack::DATETIME_FORMAT)
|
85
|
+
})
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.find_between_dates(scope, from_date, to_date)
|
90
|
+
find(scope, :params => {
|
91
|
+
:start => from_date.utc.strftime(OpenStack::DATETIME_FORMAT),
|
92
|
+
:end => to_date.utc.strftime(OpenStack::DATETIME_FORMAT)
|
93
|
+
})
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
class ServerUsage < Base
|
100
|
+
|
101
|
+
schema do
|
102
|
+
attribute :name, :string
|
103
|
+
attribute :vcpus, :integer
|
104
|
+
attribute :uptime, :integer
|
105
|
+
attribute :hours, :float
|
106
|
+
attribute :local_gb, :integer
|
107
|
+
attribute :tenant_id, :string
|
108
|
+
attribute :flavor, :string
|
109
|
+
attribute :state, :string
|
110
|
+
attribute :memory_mb, :integer
|
111
|
+
attribute :started_at, :datetime
|
112
|
+
attribute :ended_at, :datetime
|
113
|
+
end
|
114
|
+
|
115
|
+
def started_at
|
116
|
+
DateTime.parse(@attributes[:started_at] + ' UTC')
|
117
|
+
end
|
118
|
+
|
119
|
+
def ended_at
|
120
|
+
return nil if @attributes[:ended_at].blank?
|
121
|
+
DateTime.parse(@attributes[:ended_at] + ' UTC')
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# This file is part of the OpenStack-ActiveResource
|
2
|
+
#
|
3
|
+
# Copyright (C) 2012 Unidata S.p.A. (Davide Guerri - d.guerri@unidata.it)
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
module OpenStack
|
19
|
+
module Nova
|
20
|
+
module Compute
|
21
|
+
|
22
|
+
class VolumeAttachment < Base
|
23
|
+
self.element_name = "volumeAttachment"
|
24
|
+
self.collection_name = "os-volume_attachments"
|
25
|
+
|
26
|
+
def self.site
|
27
|
+
superclass.site + "servers/:server_id"
|
28
|
+
end
|
29
|
+
|
30
|
+
schema do
|
31
|
+
attribute :device, :string
|
32
|
+
attribute :volume_id, :string
|
33
|
+
attribute :server_id, :string
|
34
|
+
end
|
35
|
+
|
36
|
+
validates :device, :presence => true, :format => {:with => /\A[\/\\a-zA-Z0-9]+\Z/}
|
37
|
+
validates :volume, :presence => true
|
38
|
+
validates :server, :presence => true
|
39
|
+
|
40
|
+
def initialize(attributes = {}, persisted = false)
|
41
|
+
attributes = attributes.with_indifferent_access
|
42
|
+
new_attributes = {
|
43
|
+
:device => attributes[:device],
|
44
|
+
}
|
45
|
+
|
46
|
+
new_attachment = super(new_attributes, persisted)
|
47
|
+
|
48
|
+
if attributes[:volume].present?
|
49
|
+
new_attachment.volume_id = attributes[:volume].id
|
50
|
+
else
|
51
|
+
new_attachment.volume_id = attributes[:volumeId]
|
52
|
+
end
|
53
|
+
|
54
|
+
if attributes[:server].present?
|
55
|
+
new_attachment.server_id = attributes[:server].id
|
56
|
+
else
|
57
|
+
new_attachment.server_id = attributes[:serverId]
|
58
|
+
end
|
59
|
+
|
60
|
+
new_attachment.prefix_options[:server_id] = new_attachment.server_id
|
61
|
+
|
62
|
+
new_attachment
|
63
|
+
end
|
64
|
+
|
65
|
+
# Overload ActiveRecord::encode method
|
66
|
+
# Custom encoding to deal with openstack API
|
67
|
+
def encode(options={})
|
68
|
+
to_encode = {
|
69
|
+
VolumeAttachment.element_name => {
|
70
|
+
:device => device,
|
71
|
+
:volumeId => volume_id,
|
72
|
+
:serverId => server_id
|
73
|
+
}
|
74
|
+
}
|
75
|
+
to_encode.send("to_#{self.class.format.extension}", options)
|
76
|
+
end
|
77
|
+
|
78
|
+
def server
|
79
|
+
Server.find(server_id) if server_id.present?
|
80
|
+
end
|
81
|
+
|
82
|
+
def server=(server)
|
83
|
+
@attributes[:server_id] = server.id unless !persisted?
|
84
|
+
end
|
85
|
+
|
86
|
+
def volume
|
87
|
+
Volume::Volume.find(volume_id) if volume_id.present?
|
88
|
+
end
|
89
|
+
|
90
|
+
def volume=(volume)
|
91
|
+
@attributes[:volume_id] = volume.id unless !persisted?
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|