module CloudstackCli::Helper
Constants
- ASYNC_STATES
Public Instance Methods
Source
# File lib/cloudstack-cli/helper.rb 9 def ask_number(question) 10 number = ask(question).to_i - 1 11 number < 0 ? 0 : number 12 end
Source
# File lib/cloudstack-cli/helper.rb 139 def bootstrap_server(args = {}) 140 if args[:project] && project = find_project(args[:project]) 141 project_id = project["id"] 142 project_name = project['name'] 143 end 144 145 if args[:name] 146 args['displayname'] = args[:name] 147 name = args[:name] 148 elsif args[:displayname] 149 name = args[:displayname] 150 end 151 152 unless server = client.list_virtual_machines(name: args[:name], project_id: project_id).first 153 say "Create VM #{name}...", :yellow 154 server = client.deploy_virtual_machine(args) 155 puts 156 say "VM #{name} has been created.", :green 157 else 158 say "VM #{name} already exists (#{server["state"]}).", :yellow 159 end 160 161 if args[:port_rules] && args[:port_rules].size > 0 162 create_port_rules(server, args[:port_rules]) 163 end 164 server 165 end
Source
# File lib/cloudstack-cli/helper.rb 241 def bootstrap_server_interactive 242 zones = client.list_zones 243 if zones.size > 1 244 say "Select a availability zone:", :yellow 245 print_options(zones) 246 zone = ask_number("Zone Nr.: ") 247 else 248 zone = 0 249 end 250 251 projects = client.list_projects 252 project_id = nil 253 if projects.size > 0 254 if yes?("Do you want to deploy your VM within a project? (y/N)") && projects.size > 0 255 say "Select a project", :yellow 256 print_options(projects) 257 project = ask_number("Project Nr.: ") 258 project_id = projects[project]['id'] rescue nil 259 end 260 end 261 262 say "Please provide a name for the new VM", :yellow 263 say "(spaces or special characters are NOT allowed)" 264 server_name = ask("Server name: ") 265 266 server_offerings = client.list_service_offerings 267 say "Select a computing offering:", :yellow 268 print_options(server_offerings) 269 service_offering = ask_number("Offering Nr.: ") 270 271 templates = client.list_templates(project_id: project_id, zone_id: zones[zone]["id"], template_filter: "executable") 272 say "Select a template:", :yellow 273 print_options(templates) 274 template = ask_number("Template Nr.: ") 275 276 networks = client.list_networks(project_id: project_id, zone_id: zones[zone]["id"]) 277 if networks.size > 1 278 say "Select a network:", :yellow 279 print_options(networks) 280 network = ask_number("Network Nr.: ") 281 else 282 network = 0 283 end 284 285 say "You entered the following configuration:", :yellow 286 table = [["Zone", zones[zone]["name"]]] 287 table << ["VM Name", server_name] 288 table << ["Template", templates[template]["name"]] 289 table << ["Offering", server_offerings[service_offering]["name"]] 290 table << ["Network", networks[network]["name"]] 291 table << ["Project", projects[project]["name"]] if project 292 print_table table 293 294 if yes? "Do you want to deploy this VM? (y/N)" 295 bootstrap_server( 296 name: server_name, 297 zone_id: zones[zone]["id"], 298 template_id: templates[template]["id"], 299 serviceoffering_id: server_offerings[service_offering]["id"], 300 network_ids: network ? networks[network]["id"] : nil, 301 project_id: project_id 302 ) 303 end 304 end
Source
# File lib/cloudstack-cli/helper.rb 178 def create_port_rules(server, port_rules, async = true) 179 frontendip_id = nil 180 jobs = [] 181 client.verbose = async 182 project_id = server['projectid'] || nil 183 port_rules.each do |pf_rule| 184 pf_rule = pf_rule_to_object(pf_rule) 185 if pf_rule[:ipaddress] 186 pub_ip = client.list_public_ip_addresses( 187 network_id: get_server_default_nic(server)["networkid"], 188 project_id: project_id, 189 ipaddress: pf_rule[:ipaddress] 190 ) 191 ip_addr = pub_ip.find { |addr| addr['ipaddress'] == pf_rule[:ipaddress]} if pub_ip 192 if ip_addr 193 frontendip = ip_addr['id'] 194 else 195 say "Error: IP #{pf_rule[:ipaddress]} not found.", :red 196 next 197 end 198 end 199 200 # check if there is already an existing rule 201 rules = client.list_port_forwarding_rules( 202 networkid: get_server_default_nic(server)["networkid"], 203 ipaddressid: frontendip_id, 204 projectid: project_id 205 ) 206 existing_pf_rules = rules.find do |rule| 207 # remember matching address for additional rules 208 frontendip_id = rule['ipaddressid'] if rule['virtualmachineid'] == server['id'] 209 210 rule['virtualmachineid'] == server['id'] && 211 rule['publicport'] == pf_rule[:publicport] && 212 rule['privateport'] == pf_rule[:privateport] && 213 rule['protocol'] == pf_rule[:protocol] 214 end 215 216 if existing_pf_rules 217 say "Port forwarding rule on port #{pf_rule[:privateport]} for VM #{server["name"]} already exists.", :yellow 218 else 219 unless frontendip_id 220 frontendip_id = client.associate_ip_address( 221 network_id: get_server_default_nic(server)["networkid"], 222 project_id: project_id 223 )['ipaddress']['id'] 224 end 225 args = pf_rule.merge({ 226 ipaddressid: frontendip_id, 227 virtualmachineid: server["id"] 228 }) 229 if async 230 say "Create port forwarding rule #{pf_rule[:ipaddress]}:#{port} for VM #{server["name"]}.", :yellow 231 client.create_port_forwarding_rule(args) 232 return 233 else 234 jobs << client.create_port_forwarding_rule(args, {sync: true})['jobid'] 235 end 236 end 237 end 238 jobs 239 end
Source
# File lib/cloudstack-cli/helper.rb 167 def create_server(args = {}) 168 if args[:project] && project = find_project(args[:project]) 169 project_id = project["id"] 170 project_name = project['name'] 171 end 172 unless server = client.list_virtual_machines(name: args[:name], project_id: project_id) 173 server = client.deploy_virtual_machine(args) 174 end 175 server 176 end
Source
# File lib/cloudstack-cli/helper.rb 306 def get_server_default_nic(server) 307 server['nic'].each do |nic| 308 return nic if nic['isdefault'] 309 end 310 end
Source
# File lib/cloudstack-cli/helper.rb 312 def pf_rule_to_object(pf_rule) 313 pf_rule = pf_rule.split(":") 314 { 315 ipaddress: (pf_rule[0] == '' ? nil : pf_rule[0]), 316 privateport: pf_rule[1], 317 publicport: (pf_rule[2] || pf_rule[1]), 318 protocol: (pf_rule[3] || 'tcp').downcase 319 } 320 end
Source
# File lib/cloudstack-cli/helper.rb 125 def print_job_status(jobs, spinner, opts = {t_start: Time.now}) 126 print ("\r" + "\e[A\e[K" * (jobs.size + 1)) unless opts[:no_clear] 127 jobs.each_with_index do |job, i| 128 print "#{job[:name]} : job #{ASYNC_STATES[job[:status]]} " 129 puts job[:status] == 0 ? spinner.first : "" 130 end 131 t_elapsed = opts[:t_start] ? (Time.now - opts[:t_start]).round(1) : 0 132 completed = jobs.count{|j| j[:status] == 1 } 133 say "Completed: #{completed} of #{jobs.size} (#{t_elapsed}s)", :magenta 134 sleep opts[:sleeptime] || 0.1 135 spinner.push spinner.shift 136 spinner 137 end
Source
# File lib/cloudstack-cli/helper.rb 3 def print_options(options, attr = 'name') 4 options.to_enum.with_index(1).each do |option, i| 5 puts "#{i}: #{option[attr]}" 6 end 7 end
Source
# File lib/cloudstack-cli/helper.rb 64 def run_background_jobs(jobs, command) 65 view_thread = Thread.new do 66 chars = %w(| / - \\) 67 call = 0 68 opts = {t_start: Time.now} 69 70 while jobs.count{|job| job[:status] < 1 } > 0 do 71 if call.modulo(40) == 0 72 t = Thread.new { jobs = update_jobs(jobs, command) } 73 while t.alive? 74 chars = print_job_status(jobs, chars, 75 call == 0 ? opts.merge(no_clear: true) : opts 76 ) 77 call += 1 78 end 79 t.join 80 else 81 chars = print_job_status(jobs, chars, 82 call == 0 ? opts.merge(no_clear: true) : opts 83 ) 84 call += 1 85 end 86 end 87 print_job_status(jobs, chars, 88 call == 0 ? opts.merge(no_clear: true) : opts 89 ) 90 end 91 view_thread.join 92 end
Source
# File lib/cloudstack-cli/helper.rb 49 def update_job_status(jobs) 50 jobs.each do |job| 51 job[:status] = 0 unless job[:status] 52 if job[:status] == 0 53 result = client.query_async_job_result(job_id: job[:id]) 54 job[:status] = result["jobstatus"] 55 # add result information for terminated jobs 56 if job[:status].between?(1, 2) 57 job[:result] = result["jobresult"] 58 end 59 end 60 end 61 jobs 62 end
Source
# File lib/cloudstack-cli/helper.rb 94 def update_jobs(jobs, command) 95 # update running job status 96 threads = jobs.select{|job| job[:status] == 0 }.map do |job| 97 Thread.new do 98 result = client.query_async_job_result(job_id: job[:job_id]) 99 job[:status] = result['jobstatus'] 100 if job[:status].between?(1, 2) 101 job[:result] = result["jobresult"] 102 end 103 end 104 end 105 threads.each(&:join) 106 107 # launch new jobs if required and possible 108 launch_capacity = (options[:concurrency] ||= 10) - jobs.count{|job| job[:status] == 0 } 109 threads = [] 110 jobs.select{|job| job[:status] == -1 }.each do |job| 111 if launch_capacity > 0 112 threads << Thread.new do 113 job[:job_id] = client.send( 114 command, job[:args], { sync: true } 115 )['jobid'] 116 job[:status] = 0 117 end 118 launch_capacity -= 1 119 end 120 end 121 threads.each(&:join) 122 jobs 123 end
Source
# File lib/cloudstack-cli/helper.rb 22 def watch_jobs(jobs) 23 chars = %w(| / - \\) 24 call = 0 25 opts = {t_start: Time.now} 26 jobs = update_job_status(jobs) 27 while jobs.count{|job| job[:status].to_i < 1 } > 0 do 28 if call.modulo(40) == 0 29 t = Thread.new { jobs = update_job_status(jobs) } 30 while t.alive? 31 chars = print_job_status(jobs, chars, 32 call == 0 ? opts.merge(no_clear: true) : opts 33 ) 34 call += 1 35 end 36 t.join 37 else 38 chars = print_job_status(jobs, chars, 39 call == 0 ? opts.merge(no_clear: true) : opts 40 ) 41 call += 1 42 end 43 end 44 print_job_status(jobs, chars, 45 call == 0 ? opts.merge(no_clear: true) : opts 46 ) 47 end