opennebula-cli 3.8.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,266 @@
1
+ # -------------------------------------------------------------------------- #
2
+ # Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
3
+ # #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
+ # not use this file except in compliance with the License. You may obtain #
6
+ # a copy of the License at #
7
+ # #
8
+ # http://www.apache.org/licenses/LICENSE-2.0 #
9
+ # #
10
+ # Unless required by applicable law or agreed to in writing, software #
11
+ # distributed under the License is distributed on an "AS IS" BASIS, #
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
13
+ # See the License for the specific language governing permissions and #
14
+ # limitations under the License. #
15
+ #--------------------------------------------------------------------------- #
16
+
17
+ require 'one_helper'
18
+
19
+ class OneVMHelper < OpenNebulaHelper::OneHelper
20
+ MULTIPLE={
21
+ :name => "multiple",
22
+ :short => "-m x",
23
+ :large => "--multiple x",
24
+ :format => Integer,
25
+ :description => "Instance multiple VMs"
26
+ }
27
+
28
+ IMAGE = {
29
+ :name => "image",
30
+ :short => "-i id|name",
31
+ :large => "--image id|name" ,
32
+ :description => "Selects the image",
33
+ :format => String,
34
+ :proc => lambda { |o, options|
35
+ OpenNebulaHelper.rname_to_id(o, "IMAGE")
36
+ }
37
+ }
38
+
39
+ FILE = {
40
+ :name => "file",
41
+ :short => "-f file",
42
+ :large => "--file file" ,
43
+ :description => "Selects the template file",
44
+ :format => String,
45
+ :proc => lambda { |o, options|
46
+ if File.file?(o)
47
+ options[:file] = o
48
+ else
49
+ exit -1
50
+ end
51
+ }
52
+ }
53
+
54
+ def self.rname
55
+ "VM"
56
+ end
57
+
58
+ def self.conf_file
59
+ "onevm.yaml"
60
+ end
61
+
62
+ def self.state_to_str(id, lcm_id)
63
+ id = id.to_i
64
+ state_str = VirtualMachine::VM_STATE[id]
65
+ short_state_str = VirtualMachine::SHORT_VM_STATES[state_str]
66
+
67
+ if short_state_str=="actv"
68
+ lcm_id = lcm_id.to_i
69
+ lcm_state_str = VirtualMachine::LCM_STATE[lcm_id]
70
+ return VirtualMachine::SHORT_LCM_STATES[lcm_state_str]
71
+ end
72
+
73
+ return short_state_str
74
+ end
75
+
76
+ def format_pool(options)
77
+ config_file = self.class.table_conf
78
+
79
+ table = CLIHelper::ShowTable.new(config_file, self) do
80
+ column :ID, "ONE identifier for Virtual Machine", :size=>6 do |d|
81
+ d["ID"]
82
+ end
83
+
84
+ column :NAME, "Name of the Virtual Machine", :left,
85
+ :size=>15 do |d|
86
+ if d["RESCHED"] == "1"
87
+ "*#{d["NAME"]}"
88
+ else
89
+ d["NAME"]
90
+ end
91
+ end
92
+
93
+ column :USER, "Username of the Virtual Machine owner", :left,
94
+ :size=>8 do |d|
95
+ helper.user_name(d, options)
96
+ end
97
+
98
+ column :GROUP, "Group of the Virtual Machine", :left,
99
+ :size=>8 do |d|
100
+ helper.group_name(d, options)
101
+ end
102
+
103
+ column :STAT, "Actual status", :size=>4 do |d,e|
104
+ OneVMHelper.state_to_str(d["STATE"], d["LCM_STATE"])
105
+ end
106
+
107
+ column :UCPU, "CPU percentage used by the VM", :size=>4 do |d|
108
+ d["CPU"]
109
+ end
110
+
111
+ column :UMEM, "Memory used by the VM", :size=>7 do |d|
112
+ OpenNebulaHelper.unit_to_str(d["MEMORY"].to_i, options)
113
+ end
114
+
115
+ column :HOST, "Host where the VM is running", :left, :size=>10 do |d|
116
+ if d['HISTORY_RECORDS'] && d['HISTORY_RECORDS']['HISTORY']
117
+ state_str = VirtualMachine::VM_STATE[d['STATE'].to_i]
118
+ if %w{ACTIVE SUSPENDED}.include? state_str
119
+ d['HISTORY_RECORDS']['HISTORY']['HOSTNAME']
120
+ end
121
+ end
122
+ end
123
+
124
+ column :TIME, "Time since the VM was submitted", :size=>10 do |d|
125
+ stime = d["STIME"].to_i
126
+ etime = d["ETIME"]=="0" ? Time.now.to_i : d["ETIME"].to_i
127
+ dtime = etime-stime
128
+ OpenNebulaHelper.period_to_str(dtime, false)
129
+ end
130
+
131
+ default :ID, :USER, :GROUP, :NAME, :STAT, :UCPU, :UMEM, :HOST,
132
+ :TIME
133
+ end
134
+
135
+ table
136
+ end
137
+
138
+ private
139
+
140
+ def factory(id=nil)
141
+ if id
142
+ OpenNebula::VirtualMachine.new_with_id(id, @client)
143
+ else
144
+ xml=OpenNebula::VirtualMachine.build_xml
145
+ OpenNebula::VirtualMachine.new(xml, @client)
146
+ end
147
+ end
148
+
149
+ def factory_pool(user_flag=-2)
150
+ OpenNebula::VirtualMachinePool.new(@client, user_flag)
151
+ end
152
+
153
+ def format_resource(vm)
154
+ str_h1="%-80s"
155
+ str="%-20s: %-20s"
156
+
157
+ CLIHelper.print_header(
158
+ str_h1 % "VIRTUAL MACHINE #{vm['ID']} INFORMATION")
159
+ puts str % ["ID", vm.id.to_s]
160
+ puts str % ["NAME", vm.name]
161
+ puts str % ["USER", vm['UNAME']]
162
+ puts str % ["GROUP", vm['GNAME']]
163
+ puts str % ["STATE", vm.state_str]
164
+ puts str % ["LCM_STATE", vm.lcm_state_str]
165
+ puts str % ["RESCHED", OpenNebulaHelper.boolean_to_str(vm['RESCHED'])]
166
+ puts str % ["HOST",
167
+ vm['/VM/HISTORY_RECORDS/HISTORY[last()]/HOSTNAME']] if
168
+ %w{ACTIVE SUSPENDED}.include? vm.state_str
169
+ puts str % ["START TIME",
170
+ OpenNebulaHelper.time_to_str(vm['/VM/STIME'])]
171
+ puts str % ["END TIME",
172
+ OpenNebulaHelper.time_to_str(vm['/VM/ETIME'])]
173
+ value=vm['DEPLOY_ID']
174
+ puts str % ["DEPLOY ID", value=="" ? "-" : value]
175
+
176
+ puts
177
+
178
+ CLIHelper.print_header(str_h1 % "VIRTUAL MACHINE MONITORING",false)
179
+ poll_attrs = {
180
+ "USED MEMORY" => "MEMORY",
181
+ "USED CPU" => "CPU",
182
+ "NET_TX" => "NET_TX",
183
+ "NET_RX" => "NET_RX"
184
+ }
185
+
186
+ poll_attrs.each { |k,v|
187
+ if k == "USED CPU"
188
+ puts str % [k,vm[v]]
189
+ elsif k == "USED MEMORY"
190
+ puts str % [k, OpenNebulaHelper.unit_to_str(vm[v].to_i, {})]
191
+ else
192
+ puts str % [k, OpenNebulaHelper.unit_to_str(vm[v].to_i/1024, {})]
193
+ end
194
+ }
195
+ puts
196
+
197
+ CLIHelper.print_header(str_h1 % "PERMISSIONS",false)
198
+
199
+ ["OWNER", "GROUP", "OTHER"].each { |e|
200
+ mask = "---"
201
+ mask[0] = "u" if vm["PERMISSIONS/#{e}_U"] == "1"
202
+ mask[1] = "m" if vm["PERMISSIONS/#{e}_M"] == "1"
203
+ mask[2] = "a" if vm["PERMISSIONS/#{e}_A"] == "1"
204
+
205
+ puts str % [e, mask]
206
+ }
207
+ puts
208
+
209
+ CLIHelper.print_header(str_h1 % "VIRTUAL MACHINE TEMPLATE",false)
210
+ puts vm.template_str
211
+
212
+ if vm.has_elements?("/VM/HISTORY_RECORDS")
213
+ puts
214
+
215
+
216
+ CLIHelper.print_header(str_h1 % "VIRTUAL MACHINE HISTORY",false)
217
+ format_history(vm)
218
+ end
219
+ end
220
+
221
+ def format_history(vm)
222
+ table=CLIHelper::ShowTable.new(nil, self) do
223
+ column :SEQ, "Sequence number", :size=>4 do |d|
224
+ d["SEQ"]
225
+ end
226
+
227
+ column :HOST, "Host name of the VM container", :left, :size=>15 do |d|
228
+ d["HOSTNAME"]
229
+ end
230
+
231
+ column :REASON, "VM state change reason", :left, :size=>6 do |d|
232
+ VirtualMachine.get_reason d["REASON"]
233
+ end
234
+
235
+ column :START, "Time when the state changed", :size=>15 do |d|
236
+ OpenNebulaHelper.time_to_str(d['STIME'])
237
+ end
238
+
239
+ column :TIME, "Total time in this state", :size=>15 do |d|
240
+ stime = d["STIME"].to_i
241
+ etime = d["ETIME"]=="0" ? Time.now.to_i : d["ETIME"].to_i
242
+ dtime = etime-stime
243
+ OpenNebulaHelper.period_to_str(dtime)
244
+ end
245
+
246
+ column :PROLOG_TIME, "Prolog time for this state", :size=>15 do |d|
247
+ stime = d["PSTIME"].to_i
248
+ if d["PSTIME"]=="0"
249
+ etime=0
250
+ else
251
+ etime = d["PETIME"]=="0" ? Time.now.to_i: d["PETIME"].to_i
252
+ end
253
+ dtime = etime-stime
254
+ OpenNebulaHelper.period_to_str(dtime)
255
+ end
256
+
257
+ default :SEQ, :HOST, :REASON, :START, :TIME, :PROLOG_TIME
258
+ end
259
+
260
+ vm_hash=vm.to_hash
261
+
262
+ history=[vm_hash['VM']['HISTORY_RECORDS']['HISTORY']].flatten
263
+
264
+ table.show(history)
265
+ end
266
+ end
@@ -0,0 +1,156 @@
1
+ # -------------------------------------------------------------------------- #
2
+ # Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
3
+ # #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
+ # not use this file except in compliance with the License. You may obtain #
6
+ # a copy of the License at #
7
+ # #
8
+ # http://www.apache.org/licenses/LICENSE-2.0 #
9
+ # #
10
+ # Unless required by applicable law or agreed to in writing, software #
11
+ # distributed under the License is distributed on an "AS IS" BASIS, #
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
13
+ # See the License for the specific language governing permissions and #
14
+ # limitations under the License. #
15
+ #--------------------------------------------------------------------------- #
16
+
17
+ require 'one_helper'
18
+
19
+ class OneVNetHelper < OpenNebulaHelper::OneHelper
20
+ def self.rname
21
+ "VNET"
22
+ end
23
+
24
+ def self.conf_file
25
+ "onevnet.yaml"
26
+ end
27
+
28
+ def self.type_to_str(id)
29
+ id = id.to_i
30
+ type_str = VirtualNetwork::VN_TYPES[id]
31
+ return VirtualNetwork::SHORT_VN_TYPES[type_str]
32
+ end
33
+
34
+ def format_pool(options)
35
+ config_file = self.class.table_conf
36
+
37
+ table = CLIHelper::ShowTable.new(config_file, self) do
38
+ column :ID, "ONE identifier for Virtual Network", :size=>4 do |d|
39
+ d["ID"]
40
+ end
41
+
42
+ column :USER, "Username of the Virtual Network owner", :left,
43
+ :size=>12 do |d|
44
+ helper.user_name(d, options)
45
+ end
46
+
47
+ column :GROUP, "Group of the Virtual Network", :left,
48
+ :size=>12 do |d|
49
+ helper.group_name(d, options)
50
+ end
51
+
52
+ column :NAME, "Name of the Virtual Network", :left,
53
+ :size=>15 do |d|
54
+ d["NAME"]
55
+ end
56
+
57
+ column :CLUSTER, "Name of the Cluster", :left, :size=>10 do |d|
58
+ OpenNebulaHelper.cluster_str(d["CLUSTER"])
59
+ end
60
+
61
+ column :TYPE, "Type of Virtual Network", :size=>6 do |d|
62
+ OneVNetHelper.type_to_str(d["TYPE"])
63
+ end
64
+
65
+ column :SIZE, "Size of the Virtual Network", :size=>5 do |d|
66
+ d["SIZE"]
67
+ end
68
+
69
+ column :BRIDGE, "Bridge associated to the Virtual Network", :left,
70
+ :size=>8 do |d|
71
+ d["BRIDGE"]
72
+ end
73
+
74
+ column :LEASES, "Number of this Virtual Network's given leases",
75
+ :size=>6 do |d|
76
+ d["TOTAL_LEASES"]
77
+ end
78
+
79
+ default :ID, :USER, :GROUP, :NAME, :CLUSTER, :TYPE, :BRIDGE, :LEASES
80
+ end
81
+
82
+ table
83
+ end
84
+
85
+ private
86
+
87
+ def factory(id=nil)
88
+ if id
89
+ OpenNebula::VirtualNetwork.new_with_id(id, @client)
90
+ else
91
+ xml=OpenNebula::VirtualNetwork.build_xml
92
+ OpenNebula::VirtualNetwork.new(xml, @client)
93
+ end
94
+ end
95
+
96
+ def factory_pool(user_flag=-2)
97
+ OpenNebula::VirtualNetworkPool.new(@client, user_flag)
98
+ end
99
+
100
+ def format_resource(vn)
101
+ str_h1="%-80s"
102
+ CLIHelper.print_header(str_h1 %
103
+ ["VIRTUAL NETWORK #{vn.id.to_s} INFORMATION"])
104
+
105
+ str="%-15s: %-20s"
106
+ puts str % ["ID", vn.id.to_s]
107
+ puts str % ["NAME", vn['NAME']]
108
+ puts str % ["USER", vn['UNAME']]
109
+ puts str % ["GROUP", vn['GNAME']]
110
+ puts str % ["CLUSTER", OpenNebulaHelper.cluster_str(vn['CLUSTER'])]
111
+ puts str % ["TYPE", vn.type_str]
112
+ puts str % ["BRIDGE", vn["BRIDGE"]]
113
+ puts str % ["VLAN", OpenNebulaHelper.boolean_to_str(vn['VLAN'])]
114
+ puts str % ["PHYSICAL DEVICE", vn["PHYDEV"]] if vn["PHYDEV"]
115
+ puts str % ["VLAN ID", vn["VLAN_ID"]] if vn["VLAN_ID"]
116
+ puts str % ["USED LEASES", vn['TOTAL_LEASES']]
117
+ puts
118
+
119
+ CLIHelper.print_header(str_h1 % "PERMISSIONS",false)
120
+
121
+ ["OWNER", "GROUP", "OTHER"].each { |e|
122
+ mask = "---"
123
+ mask[0] = "u" if vn["PERMISSIONS/#{e}_U"] == "1"
124
+ mask[1] = "m" if vn["PERMISSIONS/#{e}_M"] == "1"
125
+ mask[2] = "a" if vn["PERMISSIONS/#{e}_A"] == "1"
126
+
127
+ puts str % [e, mask]
128
+ }
129
+ puts
130
+
131
+ CLIHelper.print_header(str_h1 % ["VIRTUAL NETWORK TEMPLATE"], false)
132
+
133
+ puts vn.template_str(false)
134
+
135
+ if vn.type_str == "RANGED"
136
+ puts
137
+ CLIHelper.print_header(str_h1 % ["RANGE"], false)
138
+ puts str % ["IP_START", vn['RANGE/IP_START']]
139
+ puts str % ["IP_END", vn['RANGE/IP_END']]
140
+ end
141
+
142
+ lease_types = [ ["LEASES ON HOLD", 'LEASE[USED=1 and VID=-1]'],
143
+ ["USED LEASES", 'LEASE[USED=1 and VID>-1]'],
144
+ ["FREE LEASES", 'LEASE[USED=0]'] ]
145
+
146
+ lease_types.each { |pair|
147
+ leases_str = vn.template_like_str('/VNET/LEASES', false, pair[1])
148
+
149
+ if !leases_str.empty?
150
+ puts
151
+ CLIHelper.print_header(str_h1 % [pair[0]], false)
152
+ puts leases_str
153
+ end
154
+ }
155
+ end
156
+ end
data/lib/one_helper.rb ADDED
@@ -0,0 +1,609 @@
1
+ # -------------------------------------------------------------------------- #
2
+ # Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
3
+ # #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
+ # not use this file except in compliance with the License. You may obtain #
6
+ # a copy of the License at #
7
+ # #
8
+ # http://www.apache.org/licenses/LICENSE-2.0 #
9
+ # #
10
+ # Unless required by applicable law or agreed to in writing, software #
11
+ # distributed under the License is distributed on an "AS IS" BASIS, #
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
13
+ # See the License for the specific language governing permissions and #
14
+ # limitations under the License. #
15
+ #--------------------------------------------------------------------------- #
16
+
17
+ require 'cli_helper'
18
+
19
+ require 'OpenNebula'
20
+ include OpenNebula
21
+
22
+ module OpenNebulaHelper
23
+ ONE_VERSION=<<-EOT
24
+ OpenNebula #{OpenNebula::VERSION}
25
+ Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org)
26
+
27
+ Licensed under the Apache License, Version 2.0 (the "License"); you may
28
+ not use this file except in compliance with the License. You may obtain
29
+ a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
30
+ EOT
31
+
32
+ if ONE_LOCATION
33
+ TABLE_CONF_PATH=ONE_LOCATION+"/etc/cli"
34
+ else
35
+ TABLE_CONF_PATH="/etc/one/cli"
36
+ end
37
+
38
+ EDITOR_PATH='/usr/bin/vi'
39
+
40
+ ########################################################################
41
+ # Options
42
+ ########################################################################
43
+ XML={
44
+ :name => "xml",
45
+ :short => "-x",
46
+ :large => "--xml",
47
+ :description => "Show the resource in xml format"
48
+ }
49
+
50
+ NUMERIC={
51
+ :name => "numeric",
52
+ :short => "-n",
53
+ :large => "--numeric",
54
+ :description => "Do not translate user and group IDs"
55
+ }
56
+
57
+ KILOBYTES={
58
+ :name => "kilobytes",
59
+ :short => "-k",
60
+ :large => "--kilobytes",
61
+ :description => "Show units in kilobytes"
62
+ }
63
+
64
+ DESCRIBE={
65
+ :name => "describe",
66
+ :large => "--describe",
67
+ :description => "Describe list columns"
68
+ }
69
+
70
+ # Command line VM template options
71
+ TEMPLATE_NAME_VM={
72
+ :name => 'name',
73
+ :large => '--name name',
74
+ :description =>
75
+ 'Name for the new VM',
76
+ :format => String
77
+ }
78
+
79
+ TEMPLATE_OPTIONS=[
80
+ {
81
+ :name => 'cpu',
82
+ :large => '--cpu cpu',
83
+ :description =>
84
+ 'CPU percentage reserved for the VM (1=100% one CPU)',
85
+ :format => Float
86
+ },
87
+ {
88
+ :name => 'arch',
89
+ :large => '--arch arch',
90
+ :description =>
91
+ 'Architecture of the VM, e.g.: i386 or x86_64',
92
+ :format => String
93
+ },
94
+ {
95
+ :name => 'memory',
96
+ :large => '--memory memory',
97
+ :description => 'Memory ammount given to the VM',
98
+ :format => String,
99
+ :proc => lambda do |o,options|
100
+ m=o.strip.match(/^(\d+(?:\.\d+)?)(m|mb|g|gb)?$/i)
101
+
102
+ if !m
103
+ [-1, 'Memory value malformed']
104
+ else
105
+ multiplier=case m[2]
106
+ when /(g|gb)/i
107
+ 1024
108
+ else
109
+ 1
110
+ end
111
+
112
+ value=m[1].to_f*multiplier
113
+
114
+ [0, value.floor]
115
+ end
116
+ end
117
+ },
118
+ {
119
+ :name => 'disk',
120
+ :large => '--disk disk0,disk1',
121
+ :description => 'Disks to attach. To use a disk owned by other user use user[disk]',
122
+ :format => Array
123
+ },
124
+ {
125
+ :name => 'network',
126
+ :large => '--network network0,network1',
127
+ :description => 'Networks to attach. To use a network owned by other user use user[network]',
128
+ :format => Array
129
+ },
130
+ {
131
+ :name => 'raw',
132
+ :large => '--raw string',
133
+ :description => 'Raw string to add to the template. Not to be confused with the RAW attribute',
134
+ :format => String
135
+ }
136
+ ]
137
+
138
+ TEMPLATE_OPTIONS_VM=[TEMPLATE_NAME_VM]+TEMPLATE_OPTIONS
139
+
140
+ OPTIONS = XML, NUMERIC, KILOBYTES
141
+
142
+ class OneHelper
143
+ def initialize(secret=nil, endpoint=nil)
144
+ begin
145
+ @client = OpenNebula::Client.new(secret,endpoint)
146
+ rescue Exception => e
147
+ puts e.message
148
+ exit -1
149
+ end
150
+
151
+ @translation_hash = nil
152
+ end
153
+
154
+ def create_resource(options, &block)
155
+ resource = factory
156
+
157
+ rc = block.call(resource)
158
+ if OpenNebula.is_error?(rc)
159
+ return -1, rc.message
160
+ else
161
+ puts "ID: #{resource.id.to_s}"
162
+ return 0
163
+ end
164
+ end
165
+
166
+ def list_pool(options, top=false, filter_flag=nil)
167
+ if options[:describe]
168
+ table = format_pool(options)
169
+
170
+ table.describe_columns
171
+ return 0
172
+ end
173
+
174
+ filter_flag ||= OpenNebula::Pool::INFO_ALL
175
+
176
+ pool = factory_pool(filter_flag)
177
+
178
+ rc = pool.info
179
+ return -1, rc.message if OpenNebula.is_error?(rc)
180
+
181
+ if options[:xml]
182
+ return 0, pool.to_xml(true)
183
+ else
184
+ table = format_pool(options)
185
+
186
+ if top
187
+ table.top(options) {
188
+ pool.info
189
+ pool_to_array(pool)
190
+ }
191
+ else
192
+ table.show(pool_to_array(pool), options)
193
+ end
194
+
195
+ return 0
196
+ end
197
+ end
198
+
199
+ def show_resource(id, options)
200
+ resource = retrieve_resource(id)
201
+
202
+ rc = resource.info
203
+ return -1, rc.message if OpenNebula.is_error?(rc)
204
+
205
+ if options[:xml]
206
+ return 0, resource.to_xml(true)
207
+ else
208
+ format_resource(resource)
209
+ return 0
210
+ end
211
+ end
212
+
213
+ def perform_action(id, options, verbose, &block)
214
+ resource = retrieve_resource(id)
215
+
216
+ rc = block.call(resource)
217
+ if OpenNebula.is_error?(rc)
218
+ return -1, rc.message
219
+ else
220
+ if options[:verbose]
221
+ puts "#{self.class.rname} #{id}: #{verbose}"
222
+ end
223
+ return 0
224
+ end
225
+ end
226
+
227
+ def perform_actions(ids,options,verbose,&block)
228
+ exit_code = 0
229
+ ids.each do |id|
230
+ rc = perform_action(id,options,verbose,&block)
231
+
232
+ unless rc[0]==0
233
+ puts rc[1]
234
+ exit_code=rc[0]
235
+ end
236
+ end
237
+
238
+ exit_code
239
+ end
240
+
241
+ ########################################################################
242
+ # Id translation
243
+ ########################################################################
244
+ def user_name(resource, options={})
245
+ if options[:numeric]
246
+ resource['UID']
247
+ else
248
+ resource['UNAME']
249
+ end
250
+ end
251
+
252
+ def group_name(resource, options={})
253
+ if options[:numeric]
254
+ resource['GID']
255
+ else
256
+ resource['GNAME']
257
+ end
258
+ end
259
+
260
+ ########################################################################
261
+ # Formatters for arguments
262
+ ########################################################################
263
+ def to_id(name)
264
+ return 0, name.to_i if name.match(/^[0123456789]+$/)
265
+
266
+ rc = get_pool
267
+ return rc if rc.first != 0
268
+
269
+ pool = rc[1]
270
+ poolname = self.class.rname
271
+
272
+ OneHelper.name_to_id(name, pool, poolname)
273
+ end
274
+
275
+ def self.to_id_desc
276
+ "OpenNebula #{self.rname} name or id"
277
+ end
278
+
279
+ def list_to_id(names)
280
+ rc = get_pool
281
+ return rc if rc.first != 0
282
+
283
+ pool = rc[1]
284
+ poolname = self.class.rname
285
+
286
+ result = names.split(',').collect { |name|
287
+ if name.match(/^[0123456789]+$/)
288
+ name.to_i
289
+ else
290
+ rc = OneHelper.name_to_id(name, pool, poolname)
291
+
292
+ if rc.first == -1
293
+ return rc[0], rc[1]
294
+ end
295
+
296
+ rc[1]
297
+ end
298
+ }
299
+
300
+ return 0, result
301
+ end
302
+
303
+ def self.list_to_id_desc
304
+ "Comma-separated list of OpenNebula #{self.rname} names or ids"
305
+ end
306
+
307
+ def self.name_to_id(name, pool, ename)
308
+ objects=pool.select {|object| object.name==name }
309
+
310
+ if objects.length>0
311
+ if objects.length>1
312
+ return -1, "There are multiple #{ename}s with name #{name}."
313
+ else
314
+ result = objects.first.id
315
+ end
316
+ else
317
+ return -1, "#{ename} named #{name} not found."
318
+ end
319
+
320
+ return 0, result
321
+ end
322
+
323
+ def filterflag_to_i(str)
324
+ filter_flag = case str
325
+ when "a", "all" then OpenNebula::Pool::INFO_ALL
326
+ when "m", "mine" then OpenNebula::Pool::INFO_MINE
327
+ when "g", "group" then OpenNebula::Pool::INFO_GROUP
328
+ else
329
+ if str.match(/^[0123456789]+$/)
330
+ str.to_i
331
+ else
332
+ rc = OpenNebulaHelper.rname_to_id(str, "USER")
333
+ if rc.first==-1
334
+ return rc
335
+ else
336
+ rc[1]
337
+ end
338
+ end
339
+ end
340
+
341
+ return 0, filter_flag
342
+ end
343
+
344
+ def self.filterflag_to_i_desc
345
+ desc=<<-EOT
346
+ a, all all the known #{self.rname}s
347
+ m, mine the #{self.rname} belonging to the user in ONE_AUTH
348
+ g, group 'mine' plus the #{self.rname} belonging to the groups
349
+ the user is member of
350
+ uid #{self.rname} of the user identified by this uid
351
+ user #{self.rname} of the user identified by the username
352
+ EOT
353
+ end
354
+
355
+ def self.table_conf
356
+ path = "#{ENV["HOME"]}/.one/cli/#{self.conf_file}"
357
+
358
+ if File.exists?(path)
359
+ return path
360
+ else
361
+ return "#{TABLE_CONF_PATH}/#{self.conf_file}"
362
+ end
363
+ end
364
+
365
+ private
366
+
367
+ def retrieve_resource(id)
368
+ factory(id)
369
+ end
370
+
371
+ def pool_to_array(pool)
372
+ if !pool.instance_of?(Hash)
373
+ phash = pool.to_hash
374
+ else
375
+ phash = pool
376
+ end
377
+
378
+ rname = self.class.rname
379
+
380
+ if phash["#{rname}_POOL"] &&
381
+ phash["#{rname}_POOL"]["#{rname}"]
382
+ if phash["#{rname}_POOL"]["#{rname}"].instance_of?(Array)
383
+ phash = phash["#{rname}_POOL"]["#{rname}"]
384
+ else
385
+ phash = [phash["#{rname}_POOL"]["#{rname}"]]
386
+ end
387
+ else
388
+ phash = Array.new
389
+ end
390
+
391
+ phash
392
+ end
393
+
394
+ def get_pool
395
+ user_flag = OpenNebula::Pool::INFO_ALL
396
+ pool = factory_pool(user_flag)
397
+
398
+ rc = pool.info
399
+ if OpenNebula.is_error?(rc)
400
+ return -1, "OpenNebula #{self.class.rname} name not " <<
401
+ "found, use the ID instead"
402
+ end
403
+
404
+ return 0, pool
405
+ end
406
+ end
407
+
408
+ def OpenNebulaHelper.rname_to_id(name, poolname)
409
+ return 0, name.to_i if name.match(/^[0123456789]+$/)
410
+
411
+ client = OpenNebula::Client.new
412
+
413
+ pool = case poolname
414
+ when "HOST" then OpenNebula::HostPool.new(client)
415
+ when "GROUP" then OpenNebula::GroupPool.new(client)
416
+ when "USER" then OpenNebula::UserPool.new(client)
417
+ when "DATASTORE" then OpenNebula::DatastorePool.new(client)
418
+ when "CLUSTER" then OpenNebula::ClusterPool.new(client)
419
+ when "VNET" then OpenNebula::VirtualNetworkPool.new(client)
420
+ when "IMAGE" then OpenNebula::ImagePool.new(client)
421
+ when "VMTEMPLATE" then OpenNebula::TemplatePool.new(client)
422
+ when "VM" then OpenNebula::VirtualMachinePool.new(client)
423
+ end
424
+
425
+ rc = pool.info
426
+ if OpenNebula.is_error?(rc)
427
+ return -1, "OpenNebula #{poolname} name not found," <<
428
+ " use the ID instead"
429
+ end
430
+
431
+ OneHelper.name_to_id(name, pool, poolname)
432
+ end
433
+
434
+ def OpenNebulaHelper.rname_to_id_desc(poolname)
435
+ "OpenNebula #{poolname} name or id"
436
+ end
437
+
438
+ def OpenNebulaHelper.boolean_to_str(str)
439
+ if str.to_i == 1
440
+ "Yes"
441
+ else
442
+ "No"
443
+ end
444
+ end
445
+
446
+ def OpenNebulaHelper.time_to_str(time)
447
+ value=time.to_i
448
+ if value==0
449
+ value='-'
450
+ else
451
+ value=Time.at(value).strftime("%m/%d %H:%M:%S")
452
+ end
453
+ end
454
+
455
+ def OpenNebulaHelper.period_to_str(time, print_seconds=true)
456
+ seconds=time.to_i
457
+ minutes, seconds=seconds.divmod(60)
458
+ hours, minutes=minutes.divmod(60)
459
+ days, hours=hours.divmod(24)
460
+
461
+ if print_seconds
462
+ "%3dd %02dh%02dm%02ds" % [days, hours, minutes, seconds]
463
+ else
464
+ "%3dd %02dh%02dm" % [days, hours, minutes]
465
+ end
466
+ end
467
+
468
+ BinarySufix = ["K", "M", "G", "T" ]
469
+
470
+ def OpenNebulaHelper.unit_to_str(value, options, unit="K")
471
+ if options[:kilobytes]
472
+ value
473
+ else
474
+ i=BinarySufix.index(unit).to_i
475
+
476
+ while value > 1024 && i < 3 do
477
+ value /= 1024.0
478
+ i+=1
479
+ end
480
+
481
+ value = (value * 10).round / 10.0
482
+
483
+ value = value.to_i if value - value.round == 0
484
+ st = value.to_s + BinarySufix[i]
485
+ end
486
+ end
487
+
488
+ # If the cluster name is empty, returns a '-' char.
489
+ #
490
+ # @param str [String || Hash] Cluster name, or empty Hash (when <CLUSTER/>)
491
+ # @return [String] the same Cluster name, or '-' if it is empty
492
+ def OpenNebulaHelper.cluster_str(str)
493
+ if str != nil && !str.empty?
494
+ str
495
+ else
496
+ "-"
497
+ end
498
+ end
499
+
500
+ def OpenNebulaHelper.update_template(id, resource, path=nil)
501
+ unless path
502
+ require 'tempfile'
503
+
504
+ tmp = Tempfile.new(id.to_s)
505
+ path = tmp.path
506
+
507
+ rc = resource.info
508
+
509
+ if OpenNebula.is_error?(rc)
510
+ puts rc.message
511
+ exit -1
512
+ end
513
+
514
+ tmp << resource.template_str
515
+ tmp.flush
516
+
517
+ editor_path = ENV["EDITOR"] ? ENV["EDITOR"] : EDITOR_PATH
518
+ system("#{editor_path} #{path}")
519
+
520
+ unless $?.exitstatus == 0
521
+ puts "Editor not defined"
522
+ exit -1
523
+ end
524
+
525
+ tmp.close
526
+ end
527
+
528
+ str = File.read(path)
529
+ str
530
+ end
531
+
532
+ def self.parse_user_object(user_object)
533
+ reg=/^([^\[]+)(?:\[([^\]]+)\])?$/
534
+
535
+ m=user_object.match(reg)
536
+
537
+ return nil if !m
538
+
539
+ user=nil
540
+ if m[2]
541
+ user=m[1]
542
+ object=m[2]
543
+ else
544
+ object=m[1]
545
+ end
546
+
547
+ [user, object]
548
+ end
549
+
550
+ def self.create_disk_net(objects, section, name)
551
+ template=''
552
+
553
+ objects.each do |obj|
554
+ res=parse_user_object(obj)
555
+ return [-1, "#{section.capitalize} \"#{obj}\" malformed"] if !res
556
+ user, object=*res
557
+
558
+ template<<"#{section.upcase}=[\n"
559
+ template<<" #{name.upcase}_UNAME=\"#{user}\",\n" if user
560
+ if object.match(/^\d$/)
561
+ template<<" #{name.upcase}_ID=#{object}\n"
562
+ else
563
+ template<<" #{name.upcase}=\"#{object}\"\n"
564
+ end
565
+ template<<"]\n"
566
+ end if objects
567
+
568
+ [0, template]
569
+ end
570
+
571
+ def self.create_template(options)
572
+ template=''
573
+
574
+ template<<"NAME=\"#{options[:name]}\"\n" if options[:name]
575
+ template<<"OS = [ ARCH = \"#{options[:arch]}\" ]\n" if options[:arch]
576
+ template<<"CPU=#{options[:cpu]}\n" if options[:cpu]
577
+ template<<"MEMORY=#{options[:memory]}\n" if options[:memory]
578
+ template<<"#{options[:raw]}\n" if options[:raw]
579
+
580
+ if options[:disk]
581
+ res=create_disk_net(options[:disk], 'DISK', 'IMAGE')
582
+ return res if res.first!=0
583
+
584
+ template<<res.last
585
+ end
586
+
587
+ if options[:network]
588
+ res=create_disk_net(options[:network], 'NIC', 'NETWORK')
589
+ return res if res.first!=0
590
+
591
+ template<<res.last
592
+ end
593
+
594
+
595
+ [0, template]
596
+ end
597
+
598
+ def self.create_template_options_used?(options)
599
+ # Get the template options names as symbols. options hash
600
+ # uses symbols
601
+ template_options=OpenNebulaHelper::TEMPLATE_OPTIONS.map do |o|
602
+ o[:name].to_sym
603
+ end
604
+
605
+ # Check if one at least one of the template options is
606
+ # in options hash
607
+ (template_options-options.keys)!=template_options
608
+ end
609
+ end