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,256 @@
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
+ class OneQuotaHelper
20
+
21
+ EDITOR_PATH='/usr/bin/vi'
22
+
23
+ #---------------------------------------------------------------------------
24
+ # Tables to format user quotas
25
+ #---------------------------------------------------------------------------
26
+ TABLE_DS = CLIHelper::ShowTable.new(nil, self) do
27
+ column :"DATASTORE ID", "", :size=>12 do |d|
28
+ d["ID"] if !d.nil?
29
+ end
30
+
31
+ column :"IMAGES", "", :right, :size=>20 do |d|
32
+ "%8d / %8d" % [d["IMAGES_USED"], d["IMAGES"]] if !d.nil?
33
+ end
34
+
35
+ column :"SIZE", "", :right, :size=>19 do |d|
36
+ "%8s / %8s" % [OpenNebulaHelper.unit_to_str(d["SIZE_USED"].to_i,{},"M"),
37
+ OpenNebulaHelper.unit_to_str(d["SIZE"].to_i,{},"M")] if !d.nil?
38
+ end
39
+ end
40
+
41
+ TABLE_NET = CLIHelper::ShowTable.new(nil, self) do
42
+ column :"NETWORK ID", "", :size=>12 do |d|
43
+ d["ID"] if !d.nil?
44
+ end
45
+
46
+ column :"LEASES", "", :right, :size=>20 do |d|
47
+ "%8d / %8d" % [d["LEASES_USED"], d["LEASES"]] if !d.nil?
48
+ end
49
+ end
50
+
51
+ TABLE_VM = CLIHelper::ShowTable.new(nil, self) do
52
+
53
+ column :"NUMBER OF VMS", "", :right, :size=>20 do |d|
54
+ "%8d / %8d" % [d["VMS_USED"], d["VMS"]] if !d.nil?
55
+ end
56
+
57
+ column :"MEMORY", "", :right, :size=>20 do |d|
58
+ "%8s / %8s" % [OpenNebulaHelper.unit_to_str(d["MEMORY_USED"].to_i,{},"M"),
59
+ OpenNebulaHelper.unit_to_str(d["MEMORY"].to_i,{},"M")] if !d.nil?
60
+ end
61
+
62
+ column :"CPU", "", :right, :size=>20 do |d|
63
+ "%8.2f / %8.2f" % [d["CPU_USED"], d["CPU"]] if !d.nil?
64
+ end
65
+ end
66
+
67
+ TABLE_IMG = CLIHelper::ShowTable.new(nil, self) do
68
+ column :"IMAGE ID", "", :size=>12 do |d|
69
+ d["ID"] if !d.nil?
70
+ end
71
+
72
+ column :"RUNNING VMS", "", :right, :size=>20 do |d|
73
+ "%8d / %8d" % [d["RVMS_USED"], d["RVMS"]] if !d.nil?
74
+ end
75
+ end
76
+
77
+ HELP_QUOTA = <<-EOT.unindent
78
+ #-----------------------------------------------------------------------
79
+ # Supported quota limits:
80
+ #
81
+ # DATASTORE = [
82
+ # ID = <ID of the datastore>
83
+ # IMAGES = <Max. number of images in the datastore>
84
+ # SIZE = <Max. storage capacity (Mb) used in the datastore>
85
+ # ]
86
+ #
87
+ # VM = [
88
+ # VMS = <Max. number of VMs>
89
+ # MEMORY = <Max. allocated memory (Mb)>
90
+ # CPU = <Max. allocated CPU>
91
+ # ]
92
+ #
93
+ # NETWORK = [
94
+ # ID = <ID of the network>
95
+ # LEASES = <Max. number of IP leases from the network>
96
+ # ]
97
+ #
98
+ # IMAGE = [
99
+ # ID = <ID of the image>
100
+ # RVMS = <Max. number of VMs using the image>
101
+ # ]
102
+ #
103
+ # In any quota 0 means unlimited. The usage counters "*_USED" are
104
+ # shown for information purposes and will NOT be modified.
105
+ #-----------------------------------------------------------------------
106
+ EOT
107
+
108
+ # Edits the quota template of a resource
109
+ # @param resource [PoolElement] to get the current info from
110
+ # @param path [String] path to the new contents. If nil a editor will be
111
+ # used
112
+ # @return [String] contents of the new quotas
113
+ def self.set_quota(resource, path)
114
+ str = ""
115
+
116
+ if path.nil?
117
+ require 'tempfile'
118
+
119
+ tmp = Tempfile.new('one-cli')
120
+ path = tmp.path
121
+
122
+ rc = resource.info
123
+
124
+ if OpenNebula.is_error?(rc)
125
+ puts rc.message
126
+ exit -1
127
+ end
128
+
129
+ tmp << HELP_QUOTA
130
+ tmp << resource.template_like_str("DATASTORE_QUOTA") << "\n"
131
+ tmp << resource.template_like_str("VM_QUOTA") << "\n"
132
+ tmp << resource.template_like_str("NETWORK_QUOTA") << "\n"
133
+ tmp << resource.template_like_str("IMAGE_QUOTA") << "\n"
134
+
135
+ tmp.close
136
+
137
+ editor_path = ENV["EDITOR"] ? ENV["EDITOR"] : EDITOR_PATH
138
+ system("#{editor_path} #{path}")
139
+
140
+ unless $?.exitstatus == 0
141
+ puts "Editor not defined"
142
+ exit -1
143
+ end
144
+
145
+ str = File.read(path)
146
+
147
+ File.unlink(path)
148
+ else
149
+ str = File.read(path)
150
+ end
151
+
152
+ str
153
+ end
154
+
155
+ # Retrieves a clean quota template, without any existing resource
156
+ # information
157
+ # @param path [String] path to the new contents. If nil a editor will be
158
+ # used
159
+ # @return [String] contents of the new quotas
160
+ def self.get_batch_quota(path)
161
+ str = ""
162
+
163
+ if path.nil?
164
+ require 'tempfile'
165
+
166
+ tmp = Tempfile.new('one-cli')
167
+ path = tmp.path
168
+
169
+ tmp << HELP_QUOTA << "\n"
170
+
171
+ tmp.close
172
+
173
+ editor_path = ENV["EDITOR"] ? ENV["EDITOR"] : EDITOR_PATH
174
+ system("#{editor_path} #{path}")
175
+
176
+ unless $?.exitstatus == 0
177
+ puts "Editor not defined"
178
+ exit -1
179
+ end
180
+
181
+ str = File.read(path)
182
+
183
+ File.unlink(path)
184
+ else
185
+ str = File.read(path)
186
+ end
187
+
188
+ str
189
+ end
190
+
191
+ # Edits the quota template of a resource, adding the quotas set in str
192
+ # @param resource [PoolElement] to get the current info from
193
+ # @param str [String] quota template, created by get_batch_quota()
194
+ # @return [String, OpenNebula::Error] merged contents of the new quotas on
195
+ # success, Error if the user info could not be retrieved
196
+ def self.merge_quota(resource, str)
197
+ rc = resource.info
198
+
199
+ if OpenNebula.is_error?(rc)
200
+ return rc
201
+ end
202
+
203
+ # Instead of parsing the existing quotas, and deleting the ones that
204
+ # conflict with the batch quota string, the new quotas are placed at
205
+ # the end of the template sent to opennebula. This relies on the core
206
+ # reading them in order and replacing the quotas with each new
207
+ # appearance
208
+
209
+ tmp_str = ""
210
+
211
+ tmp_str << resource.template_like_str("DATASTORE_QUOTA") << "\n"
212
+ tmp_str << resource.template_like_str("VM_QUOTA") << "\n"
213
+ tmp_str << resource.template_like_str("NETWORK_QUOTA") << "\n"
214
+ tmp_str << resource.template_like_str("IMAGE_QUOTA") << "\n"
215
+
216
+ tmp_str << str
217
+
218
+ return tmp_str
219
+ end
220
+
221
+ # Outputs formated quota information to stdout
222
+ # @param qh [Hash] with the quotas for a given resource
223
+ #
224
+ def self.format_quota(qh)
225
+ str_h1="%-80s"
226
+
227
+ puts
228
+
229
+ CLIHelper.print_header(str_h1 % "RESOURCE USAGE & QUOTAS",false)
230
+
231
+ puts
232
+
233
+ vm_quotas = [qh['VM_QUOTA']['VM']].flatten
234
+ if !vm_quotas[0].nil?
235
+ TABLE_VM.show(vm_quotas, {})
236
+ puts
237
+ end
238
+
239
+ ds_quotas = [qh['DATASTORE_QUOTA']['DATASTORE']].flatten
240
+ if !ds_quotas[0].nil?
241
+ TABLE_DS.show(ds_quotas, {})
242
+ puts
243
+ end
244
+
245
+ net_quotas = [qh['NETWORK_QUOTA']['NETWORK']].flatten
246
+ if !net_quotas[0].nil?
247
+ TABLE_NET.show(net_quotas, {})
248
+ puts
249
+ end
250
+
251
+ image_quotas = [qh['IMAGE_QUOTA']['IMAGE']].flatten
252
+ if !image_quotas[0].nil?
253
+ TABLE_IMG.show(image_quotas, {})
254
+ end
255
+ end
256
+ end
@@ -0,0 +1,123 @@
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 OneTemplateHelper < OpenNebulaHelper::OneHelper
20
+ VM_NAME={
21
+ :name => "name",
22
+ :large => "--name name",
23
+ :format => String,
24
+ :description => <<-EOT.strip
25
+ Name of the new VM or TEMPLATE. When instantiating
26
+ multiple VMs you can use the\"%i\" wildcard to produce
27
+ different names such as vm-0, vm-1...
28
+ EOT
29
+ }
30
+
31
+ MULTIPLE={
32
+ :name => "multiple",
33
+ :short => "-m x",
34
+ :large => "--multiple x",
35
+ :format => Integer,
36
+ :description => "Instance multiple VMs"
37
+ }
38
+
39
+ def self.rname
40
+ "VMTEMPLATE"
41
+ end
42
+
43
+ def self.conf_file
44
+ "onetemplate.yaml"
45
+ end
46
+
47
+ def format_pool(options)
48
+ config_file = self.class.table_conf
49
+
50
+ table = CLIHelper::ShowTable.new(config_file, self) do
51
+ column :ID, "ONE identifier for the Template", :size=>4 do |d|
52
+ d["ID"]
53
+ end
54
+
55
+ column :NAME, "Name of the Template", :left, :size=>27 do |d|
56
+ d["NAME"]
57
+ end
58
+
59
+ column :USER, "Username of the Template owner", :left,
60
+ :size=>15 do |d|
61
+ helper.user_name(d, options)
62
+ end
63
+
64
+ column :GROUP, "Group of the Template", :left, :size=>15 do |d|
65
+ helper.group_name(d, options)
66
+ end
67
+
68
+ column :REGTIME, "Registration time of the Template",
69
+ :size=>15 do |d|
70
+ OpenNebulaHelper.time_to_str(d["REGTIME"])
71
+ end
72
+
73
+ default :ID, :USER, :GROUP, :NAME, :REGTIME
74
+ end
75
+
76
+ table
77
+ end
78
+
79
+ private
80
+
81
+ def factory(id=nil)
82
+ if id
83
+ OpenNebula::Template.new_with_id(id, @client)
84
+ else
85
+ xml=OpenNebula::Template.build_xml
86
+ OpenNebula::Template.new(xml, @client)
87
+ end
88
+ end
89
+
90
+ def factory_pool(user_flag=-2)
91
+ OpenNebula::TemplatePool.new(@client, user_flag)
92
+ end
93
+
94
+ def format_resource(template)
95
+ str="%-15s: %-20s"
96
+ str_h1="%-80s"
97
+
98
+ CLIHelper.print_header(
99
+ str_h1 % "TEMPLATE #{template['ID']} INFORMATION")
100
+ puts str % ["ID", template.id.to_s]
101
+ puts str % ["NAME", template.name]
102
+ puts str % ["USER", template['UNAME']]
103
+ puts str % ["GROUP", template['GNAME']]
104
+ puts str % ["REGISTER TIME",
105
+ OpenNebulaHelper.time_to_str(template['REGTIME'])]
106
+ puts
107
+
108
+ CLIHelper.print_header(str_h1 % "PERMISSIONS",false)
109
+
110
+ ["OWNER", "GROUP", "OTHER"].each { |e|
111
+ mask = "---"
112
+ mask[0] = "u" if template["PERMISSIONS/#{e}_U"] == "1"
113
+ mask[1] = "m" if template["PERMISSIONS/#{e}_M"] == "1"
114
+ mask[2] = "a" if template["PERMISSIONS/#{e}_A"] == "1"
115
+
116
+ puts str % [e, mask]
117
+ }
118
+ puts
119
+
120
+ CLIHelper.print_header(str_h1 % "TEMPLATE CONTENTS",false)
121
+ puts template.template_str
122
+ end
123
+ end
@@ -0,0 +1,242 @@
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
+ require 'one_helper/onequota_helper'
19
+
20
+ class OneUserHelper < OpenNebulaHelper::OneHelper
21
+ def self.rname
22
+ "USER"
23
+ end
24
+
25
+ def self.conf_file
26
+ "oneuser.yaml"
27
+ end
28
+
29
+ def self.password_to_str_desc
30
+ "User password"
31
+ end
32
+
33
+ def self.password_to_str(arg, options)
34
+ if options[:read_file]
35
+ begin
36
+ password = File.read(arg).split("\n").first
37
+ rescue
38
+ return -1, "Cannot read file: #{arg}"
39
+ end
40
+ else
41
+ password = arg.dup
42
+ end
43
+
44
+ if options[:driver] == OpenNebula::User::X509_AUTH
45
+ password.delete!("\s")
46
+ end
47
+
48
+ if options[:sha1] || options[:driver] == OpenNebula::User::CIPHER_AUTH
49
+ require 'digest/sha1'
50
+ password = Digest::SHA1.hexdigest(password)
51
+ end
52
+
53
+ return 0, password
54
+ end
55
+
56
+ def password(options)
57
+ case options[:driver]
58
+ when OpenNebula::User::SSH_AUTH
59
+ if !options[:key]
60
+ return -1, "You have to specify the --key option"
61
+ end
62
+
63
+ require 'ssh_auth'
64
+
65
+ begin
66
+ auth = SshAuth.new(:private_key=>options[:key])
67
+ rescue Exception => e
68
+ return -1, e.message
69
+ end
70
+ when OpenNebula::User::X509_AUTH
71
+ options[:cert] ||= ENV['X509_USER_CERT']
72
+
73
+ if !options[:cert]
74
+ return -1, "You have to specify the --cert option"
75
+ end
76
+
77
+ require 'x509_auth'
78
+
79
+ begin
80
+ cert = [File.read(options[:cert])]
81
+ auth = X509Auth.new(:certs_pem=>cert)
82
+ rescue Exception => e
83
+ return -1, e.message
84
+ end
85
+ else
86
+ return -1, "You have to specify an Auth method or define a password"
87
+ end
88
+
89
+ return 0, auth.password
90
+ end
91
+
92
+ def self.login(username, options)
93
+ case options[:driver]
94
+ when OpenNebula::User::SSH_AUTH
95
+ require 'ssh_auth'
96
+
97
+ options[:key] ||= ENV['HOME']+'/.ssh/id_rsa'
98
+
99
+ begin
100
+ auth = SshAuth.new(:private_key=>options[:key])
101
+ rescue Exception => e
102
+ return -1, e.message
103
+ end
104
+ when OpenNebula::User::X509_AUTH
105
+ require 'x509_auth'
106
+
107
+ options[:cert] ||= ENV['X509_USER_CERT']
108
+ options[:key] ||= ENV['X509_USER_KEY']
109
+
110
+ begin
111
+ certs = [File.read(options[:cert])]
112
+ key = File.read(options[:key])
113
+
114
+ auth = X509Auth.new(:certs_pem=>certs, :key_pem=>key)
115
+ rescue Exception => e
116
+ return -1, e.message
117
+ end
118
+ when OpenNebula::User::X509_PROXY_AUTH
119
+ require 'x509_auth'
120
+
121
+ options[:proxy] ||= ENV['X509_PROXY_CERT']
122
+
123
+ begin
124
+ proxy = File.read(options[:proxy])
125
+
126
+ certs = proxy.scan(/(-+BEGIN CERTIFICATE-+\n[^-]*\n-+END CERTIFICATE-+)/)
127
+ certs.flatten!
128
+
129
+ rc = proxy.match(/(-+BEGIN RSA PRIVATE KEY-+\n[^-]*\n-+END RSA PRIVATE KEY-+)/)
130
+ key= rc[1]
131
+
132
+ auth = X509Auth.new(:certs_pem=>certs, :key_pem=>key)
133
+ rescue => e
134
+ return -1, e.message
135
+ end
136
+ else
137
+ return -1, "You have to specify an Auth method"
138
+ end
139
+
140
+ options[:time] ||= 3600
141
+
142
+ auth.login(username, Time.now+options[:time])
143
+
144
+ return 0, 'export ONE_AUTH=' << auth.class::LOGIN_PATH
145
+ end
146
+
147
+ def format_pool(options)
148
+ config_file = self.class.table_conf
149
+
150
+ table = CLIHelper::ShowTable.new(config_file, self) do
151
+ column :ID, "ONE identifier for the User", :size=>4 do |d|
152
+ d["ID"]
153
+ end
154
+
155
+ column :NAME, "Name of the User", :left, :size=>15 do |d|
156
+ d["NAME"]
157
+ end
158
+
159
+ column :GROUP, "Group of the User", :left, :size=>10 do |d|
160
+ helper.group_name(d, options)
161
+ end
162
+
163
+ column :AUTH, "Auth driver of the User", :left, :size=>8 do |d|
164
+ d["AUTH_DRIVER"]
165
+ end
166
+
167
+ column :VMS , "Number of VMS", :size=>9 do |d|
168
+ if d.has_key?('VM_QUOTA') and d['VM_QUOTA'].has_key?('VM')
169
+ "%3d / %3d" % [d['VM_QUOTA']['VM']["VMS_USED"], d['VM_QUOTA']['VM']["VMS"]]
170
+ else
171
+ "-"
172
+ end
173
+ end
174
+
175
+ column :MEMORY, "Total memory allocated to user VMs", :size=>17 do |d|
176
+ if d.has_key?('VM_QUOTA') and d['VM_QUOTA'].has_key?('VM')
177
+ d['VM_QUOTA']['VM']['MEMORY_USED']
178
+ "%7s / %7s" % [OpenNebulaHelper.unit_to_str(d['VM_QUOTA']['VM']["MEMORY_USED"].to_i,{},"M"),
179
+ OpenNebulaHelper.unit_to_str(d['VM_QUOTA']['VM']["MEMORY"].to_i,{},"M")]
180
+ else
181
+ "-"
182
+ end
183
+ end
184
+
185
+ column :CPU, "Total CPU allocated to user VMs", :size=>11 do |d|
186
+ if d.has_key?('VM_QUOTA') and d['VM_QUOTA'].has_key?('VM')
187
+ "%4.0f / %4.0f" % [d['VM_QUOTA']['VM']["CPU_USED"], d['VM_QUOTA']['VM']["CPU"]]
188
+ else
189
+ "-"
190
+ end
191
+ end
192
+
193
+ column :PASSWORD, "Password of the User", :size=>50 do |d|
194
+ d['PASSWORD']
195
+ end
196
+
197
+ default :ID, :NAME, :GROUP, :AUTH, :VMS, :MEMORY, :CPU
198
+ end
199
+
200
+ table
201
+ end
202
+
203
+ private
204
+
205
+ def factory(id=nil)
206
+ if id
207
+ OpenNebula::User.new_with_id(id, @client)
208
+ else
209
+ xml=OpenNebula::User.build_xml
210
+ OpenNebula::User.new(xml, @client)
211
+ end
212
+ end
213
+
214
+ def factory_pool(user_flag=-2)
215
+ #TBD OpenNebula::UserPool.new(@client, user_flag)
216
+ OpenNebula::UserPool.new(@client)
217
+ end
218
+
219
+ def format_resource(user)
220
+ str="%-15s: %-20s"
221
+ str_h1="%-80s"
222
+
223
+ CLIHelper.print_header(str_h1 % "USER #{user['ID']} INFORMATION")
224
+ puts str % ["ID", user.id.to_s]
225
+ puts str % ["NAME", user.name]
226
+ puts str % ["GROUP", user['GNAME']]
227
+ puts str % ["PASSWORD", user['PASSWORD']]
228
+ puts str % ["AUTH_DRIVER", user['AUTH_DRIVER']]
229
+
230
+ puts str % ["ENABLED",
231
+ OpenNebulaHelper.boolean_to_str(user['ENABLED'])]
232
+
233
+ puts
234
+
235
+ CLIHelper.print_header(str_h1 % "USER TEMPLATE",false)
236
+ puts user.template_str
237
+
238
+ user_hash = user.to_hash
239
+
240
+ OneQuotaHelper.format_quota(user_hash['USER'])
241
+ end
242
+ end