Statistics
| Branch: | Tag: | Revision:

one / src / vmm_mad / remotes / lib / vcenter_driver / importer.rb @ b41afe0c

History | View | Annotate | Download (40.6 KB)

1
module VCenterDriver
2

    
3
class Importer
4

    
5
VNC_ESX_HOST_FOLDER = "/tmp"
6

    
7
def self.import_wild(host_id, vm_ref, one_vm, template)
8

    
9
    begin
10
        vi_client = VCenterDriver::VIClient.new_from_host(host_id)
11
        vc_uuid   = vi_client.vim.serviceContent.about.instanceUuid
12
        vc_name   = vi_client.vim.host
13

    
14
        dpool = VCenterDriver::VIHelper.one_pool(OpenNebula::DatastorePool)
15
        if dpool.respond_to?(:message)
16
            raise "Could not get OpenNebula DatastorePool: #{dpool.message}"
17
        end
18
        ipool = VCenterDriver::VIHelper.one_pool(OpenNebula::ImagePool)
19
        if ipool.respond_to?(:message)
20
            raise "Could not get OpenNebula ImagePool: #{ipool.message}"
21
        end
22
        npool = VCenterDriver::VIHelper.one_pool(OpenNebula::VirtualNetworkPool)
23
        if npool.respond_to?(:message)
24
            raise "Could not get OpenNebula VirtualNetworkPool: #{npool.message}"
25
        end
26
        hpool = VCenterDriver::VIHelper.one_pool(OpenNebula::HostPool)
27
        if hpool.respond_to?(:message)
28
            raise "Could not get OpenNebula HostPool: #{hpool.message}"
29
        end
30

    
31
        vcenter_vm = VCenterDriver::VirtualMachine.new_from_ref(vm_ref, vi_client)
32
        vm_name    = vcenter_vm["name"]
33

    
34
        wild     = true
35
        sunstone = false
36

    
37
        #error, template_disks = vcenter_vm.import_vcenter_disks(vc_uuid, dpool, ipool, sunstone)
38
        #return OpenNebula::Error.new(error) if !error.empty?
39

    
40
        #template << template_disks
41

    
42
        # Create images or get nics information for template
43
        #error, template_nics = vcenter_vm.import_vcenter_nics(vc_uuid,
44
        #                                                      npool,
45
        #                                                      hpool,
46
        #                                                      vc_name,
47
        #                                                      vm_ref,
48
        #                                                      wild,
49
        #                                                      sunstone,
50
        #                                                      vm_name)
51
        #
52
        #return OpenNebula::Error.new(error) if !error.empty?
53

    
54
        #template << template_nics
55

    
56
        # Get DS_ID for the deployment, the wild VM needs a System DS
57
        dc_ref = vcenter_vm.get_dc.item._ref
58
        ds_ref = template.match(/^VCENTER_DS_REF *= *"(.*)" *$/)[1]
59

    
60
        ds_one = dpool.select do |e|
61
            e["TEMPLATE/TYPE"]                == "SYSTEM_DS" &&
62
            e["TEMPLATE/VCENTER_DS_REF"]      == ds_ref &&
63
            e["TEMPLATE/VCENTER_DC_REF"]      == dc_ref &&
64
            e["TEMPLATE/VCENTER_INSTANCE_ID"] == vc_uuid
65
        end.first
66
        
67
        return OpenNebula::Error.new("DS with ref #{ds_ref} is not imported in OpenNebula, aborting Wild VM import.") if !ds_one
68

    
69
        rc = one_vm.allocate(template)
70
        return rc if OpenNebula.is_error?(rc)
71

    
72
        rc = one_vm.deploy(host_id, false, ds_one.id)
73
        return rc if OpenNebula.is_error?(rc)
74

    
75
        # Set reference to template disks and nics in VM template
76
        vcenter_vm.one_item = one_vm
77
        vcenter_vm.reference_unmanaged_devices(vm_ref)
78

    
79
        # Set vnc configuration F#5074
80
        vnc_port  = one_vm["TEMPLATE/GRAPHICS/PORT"]
81
        elapsed_seconds = 0
82

    
83
        # Let's update the info to gather VNC port
84
        until vnc_port || elapsed_seconds > 30
85
            sleep(1)
86
            one_vm.info
87
            vnc_port  = one_vm["TEMPLATE/GRAPHICS/PORT"]
88
            elapsed_seconds += 1
89
        end
90

    
91
        if vnc_port
92
            vcenter_vm.one_item = one_vm
93
            extraconfig   = []
94
            extraconfig  += vcenter_vm.extraconfig_vnc
95
            spec_hash     = { :extraConfig  => extraconfig }
96
            spec = RbVmomi::VIM.VirtualMachineConfigSpec(spec_hash)
97
            vcenter_vm.item.ReconfigVM_Task(:spec => spec).wait_for_completion
98
        end
99

    
100
        # Add VCENTER_ESX_HOST to MONITOR info so VNC works for running VMs F#4242
101
        esx_host = vcenter_vm["runtime.host.name"].to_s
102
        f = File.open(File.join(VNC_ESX_HOST_FOLDER, "vcenter_vnc_#{one_vm.id}"), 'w')
103
        f.write(esx_host)
104
        f.close
105

    
106
        return one_vm.id
107

    
108
    rescue Exception => e
109
        vi_client.close_connection if vi_client
110
        return OpenNebula::Error.new("#{e.message}/#{e.backtrace}")
111
    end
112
end
113

    
114
def self.import_clusters(con_ops, options)
115
    begin
116
        STDOUT.print "\nConnecting to vCenter: #{options[:vcenter]}..."
117

    
118
        use_defaults = options.key?(:defaults)
119

    
120
        vi_client = VCenterDriver::VIClient.new(con_ops)
121

    
122
        STDOUT.print "done!\n\n"
123

    
124
        STDOUT.print "Exploring vCenter resources..."
125

    
126
        dc_folder = VCenterDriver::DatacenterFolder.new(vi_client)
127

    
128
        vcenter_instance_name = vi_client.vim.host
129
        vc_uuid   = vi_client.vim.serviceContent.about.instanceUuid
130

    
131
        # OpenNebula's ClusterPool
132
        cpool = VCenterDriver::VIHelper.one_pool(OpenNebula::ClusterPool, false)
133
        if cpool.respond_to?(:message)
134
            raise "Could not get OpenNebula ClusterPool: #{cpool.message}"
135
        end
136

    
137
        cluster_list = {}
138
        cpool.each do |c|
139
            cluster_list[c["ID"]] = c["NAME"] if c["ID"].to_i != 0
140
        end
141

    
142
        # Get OpenNebula's host pool
143
        hpool = VCenterDriver::VIHelper.one_pool(OpenNebula::HostPool, false)
144
        if hpool.respond_to?(:message)
145
            raise "Could not get OpenNebula HostPool: #{hpool.message}"
146
        end
147

    
148
        rs = dc_folder.get_unimported_hosts(hpool,vcenter_instance_name)
149

    
150
        STDOUT.print "done!\n\n"
151

    
152
        rs.each {|dc, clusters|
153

    
154
            if !use_defaults
155
                STDOUT.print "Do you want to process datacenter #{dc} (y/[n])? "
156
                next if STDIN.gets.strip.downcase != 'y'
157
            end
158

    
159
            if clusters.empty?
160
                STDOUT.puts "\n    No new clusters found in #{dc}..."
161
                next
162
            end
163

    
164
            clusters.each{ |cluster|
165
                one_cluster_id = nil
166
                rpool = nil
167
                if !use_defaults
168
                    STDOUT.print "\n  * vCenter cluster found:\n"\
169
                                 "      - Name       : \e[92m#{cluster[:simple_name]}\e[39m\n"\
170
                                 "      - Location   : #{cluster[:cluster_location]}\n"\
171
                                 "    Import cluster (y/[n])? "
172
                    next if STDIN.gets.strip.downcase != 'y'
173

    
174
                    if cluster_list.size > 0
175
                        STDOUT.print "\n    In which OpenNebula cluster do you want the vCenter cluster to be included?\n "
176

    
177
                        cluster_list_str = "\n"
178
                        cluster_list.each do |key, value|
179
                            cluster_list_str << "      - \e[94mID: " << key << "\e[39m - NAME: " << value << "\n"
180
                        end
181

    
182
                        STDOUT.print "\n    #{cluster_list_str}"
183
                        STDOUT.print "\n    Specify the ID of the cluster or press Enter if you want OpenNebula to create a new cluster for you: "
184

    
185
                        answer = STDIN.gets.strip
186
                        if !answer.empty?
187
                            one_cluster_id = answer
188
                        end
189
                    end
190

    
191
                    if !one_cluster_id
192
                        one_cluster = VCenterDriver::VIHelper.new_one_item(OpenNebula::Cluster)
193
                        rc = one_cluster.allocate("#{cluster[:cluster_name]}")
194
                        if ::OpenNebula.is_error?(rc)
195
                            STDOUT.puts "    Error creating OpenNebula cluster: #{rc.message}\n"
196
                            next
197
                        end
198
                        one_cluster_id = one_cluster.id
199
                    end
200
                else
201
                    # Defaults, add host to new cluster
202
                    one_cluster = VCenterDriver::VIHelper.new_one_item(OpenNebula::Cluster)
203
                    rc = one_cluster.allocate("#{cluster[:cluster_name]}")
204
                    if ::OpenNebula.is_error?(rc)
205
                        STDOUT.puts "    Error creating OpenNebula cluster: #{rc.message}\n"
206
                        next
207
                    end
208
                    one_cluster_id = one_cluster.id
209
                end
210

    
211

    
212

    
213
                # Generate the template and create the host in the pool
214
                one_host = VCenterDriver::ClusterComputeResource.to_one(cluster,
215
                                                                        con_ops,
216
                                                                        rpool,
217
                                                                        one_cluster_id)
218

    
219
                STDOUT.puts "\n    OpenNebula host \e[92m#{cluster[:cluster_name]}\e[39m with"\
220
                            " ID \e[94m#{one_host.id}\e[39m successfully created."
221
                STDOUT.puts
222
            }
223
        }
224
    rescue Interrupt => e
225
        puts "\n"
226
        exit 0 #Ctrl+C
227
    rescue Exception => e
228
        STDOUT.puts "    Error: #{e.message}/\n#{e.backtrace}"
229
    ensure
230
        vi_client.close_connection if vi_client
231
    end
232

    
233
end
234

    
235
def self.import_templates(con_ops, options)
236
    begin
237
        STDOUT.print "\nConnecting to vCenter: #{options[:vcenter]}..."
238

    
239
        use_defaults = options.key?(:defaults)
240

    
241
        vi_client = VCenterDriver::VIClient.new(con_ops)
242

    
243
        STDOUT.print "done!\n\n"
244

    
245
        STDOUT.print "Looking for VM Templates..."
246

    
247
        dc_folder = VCenterDriver::DatacenterFolder.new(vi_client)
248

    
249
        # Get OpenNebula's templates pool
250
        tpool = VCenterDriver::VIHelper.one_pool(OpenNebula::TemplatePool, false)
251
        if tpool.respond_to?(:message)
252
            raise "Could not get OpenNebula TemplatePool: #{tpool.message}"
253
        end
254

    
255
        rs = dc_folder.get_unimported_templates(vi_client, tpool)
256

    
257
        STDOUT.print "done!\n"
258

    
259
        # Create OpenNebula pools
260
        dpool = VCenterDriver::VIHelper.one_pool(OpenNebula::DatastorePool)
261
        if dpool.respond_to?(:message)
262
            raise "Could not get OpenNebula DatastorePool: #{dpool.message}"
263
        end
264
        ipool = VCenterDriver::VIHelper.one_pool(OpenNebula::ImagePool)
265
        if ipool.respond_to?(:message)
266
            raise "Could not get OpenNebula ImagePool: #{ipool.message}"
267
        end
268
        npool = VCenterDriver::VIHelper.one_pool(OpenNebula::VirtualNetworkPool)
269
        if npool.respond_to?(:message)
270
            raise "Could not get OpenNebula VirtualNetworkPool: #{npool.message}"
271
        end
272
        hpool = VCenterDriver::VIHelper.one_pool(OpenNebula::HostPool)
273
        if hpool.respond_to?(:message)
274
            raise "Could not get OpenNebula HostPool: #{hpool.message}"
275
        end
276

    
277
        # Get vcenter intance uuid as moref is unique for each vcenter
278
        vc_uuid = vi_client.vim.serviceContent.about.instanceUuid
279

    
280
        # Init vars
281
        allocated_images  = []
282
        allocated_nets    = []
283
        one_t             = nil
284
        template_copy_ref = nil
285

    
286
        rs.each {|dc, tmps|
287

    
288
            if !use_defaults
289
                STDOUT.print "\nDo you want to process datacenter #{dc} (y/[n])? "
290
                next if STDIN.gets.strip.downcase != 'y'
291
            end
292

    
293
            if tmps.empty?
294
                STDOUT.print "    No new VM Templates found in #{dc}...\n\n"
295
                next
296
            end
297

    
298
            tmps.each{ |t|
299
                template = nil
300
                template_copy_ref = nil
301

    
302
                if !use_defaults
303
                    STDOUT.print "\n  * VM Template found:\n"\
304
                                    "      - Name       : \e[92m#{t[:template_name]}\e[39m\n"\
305
                                    "      - Cluster    : \e[96m#{t[:cluster_name]}\e[39m\n"\
306
                                    "      - Location   : #{t[:template_location]}\n"\
307
                                    "    Import this VM template (y/[n])? "
308

    
309
                    next if STDIN.gets.strip.downcase != 'y'
310
                end
311

    
312
                allocated_images = []
313
                allocated_nets   = []
314

    
315
                # Linked Clones
316
                if !use_defaults
317

    
318
                    template = VCenterDriver::Template.new_from_ref(t[:vcenter_ref], vi_client)
319

    
320
                    STDOUT.print "\n    For faster deployment operations"\
321
                                 " and lower disk usage, OpenNebula"\
322
                                 " can create new VMs as linked clones."\
323
                                 "\n    Would you like to use Linked Clones with VMs based on this template (y/[n])? "
324

    
325
                    if STDIN.gets.strip.downcase == 'y'
326

    
327
                        STDOUT.print "\n    Linked clones requires that delta"\
328
                                     " disks must be created for each disk in the template."\
329
                                     " This operation may change the template contents."\
330
                                     " \n    Do you want OpenNebula to create a copy of the template,"\
331
                                     " so the original template remains untouched ([y]/n)? "
332

    
333
                        template = t[:template]
334
                        if STDIN.gets.strip.downcase != 'n'
335

    
336
                            STDOUT.print "\n    The new template will be named"\
337
                                         " adding a one- prefix to the name"\
338
                                         " of the original template. \n"\
339
                                         "    If you prefer a different name"\
340
                                         " please specify or press Enter"\
341
                                         " to use defaults: "
342

    
343
                            template_name = STDIN.gets.strip.downcase
344

    
345
                            STDOUT.print "\n    WARNING!!! The cloning operation can take some time"\
346
                                         " depending on the size of disks. \e[96mPlease wait...\e[39m\n"
347

    
348

    
349
                            error, template_copy_ref = template.create_template_copy(template_name)
350

    
351
                            if template_copy_ref
352

    
353
                                template = VCenterDriver::Template.new_from_ref(template_copy_ref, vi_client)
354

    
355
                                one_template = VCenterDriver::Template.get_xml_template(template, vc_uuid, vi_client, options[:vcenter], dc)
356

    
357
                                if one_template
358
                                    #Now create delta disks
359
                                    STDOUT.print "\n    Delta disks are being created, please be patient..."
360

    
361
                                    lc_error, use_lc = template.create_delta_disks
362
                                    if lc_error
363
                                        STDOUT.print "\n    ERROR. Something was wrong with the create delta disks on the template operation: #{lc_error}.\n"\
364
                                                    "\n    Linked Clones will not be used with this template.\n"
365
                                    else
366
                                        one_template[:one] << "\nVCENTER_LINKED_CLONES=\"YES\"\n"
367
                                        t = one_template
368
                                    end
369
                                else
370
                                    STDOUT.print "\n    ERROR. Something was wrong obtaining the info from the template's copy.\n"\
371
                                                 "\n    Linked Clones will not be used with this template.\n"
372
                                    template.delete_template if template_copy_ref
373
                                end
374

    
375
                            else
376
                                STDOUT.print "\n    ERROR. #{error}\n"
377
                            end
378

    
379
                        else
380
                            # Create linked clones on top of the existing template
381
                            # Create a VirtualMachine object from the template_copy_ref
382
                            STDOUT.print "\n    Delta disks are being created, \e[96please be patient...\e[39m"
383

    
384
                            lc_error, use_lc = template.create_delta_disks
385
                            if lc_error
386
                                STDOUT.print "\n    ERROR. Something was wrong with the create delta disks on the template operation: #{lc_error}.\n"\
387
                                             "\n    Linked Clones will not be used with this template.\n"
388
                            end
389
                            t[:one] << "\nVCENTER_LINKED_CLONES=\"YES\"\n" if use_lc
390
                        end
391
                    end
392
                end
393

    
394
                vcenter_vm_folder = ""
395
                if !use_defaults
396
                    STDOUT.print "\n\n    Do you want to specify a folder where"\
397
                                    " the deployed VMs based on this template will appear"\
398
                                    " in vSphere's VM and Templates section?"\
399
                                    "\n    If no path is set, VMs will be placed in the same"\
400
                                    " location where the template lives."\
401
                                    "\n    Please specify a path using slashes to separate folders"\
402
                                    " e.g /Management/VMs or press Enter to use defaults: "\
403

    
404
                    vcenter_vm_folder = STDIN.gets.strip
405
                    t[:one] << "VCENTER_VM_FOLDER=\"#{vcenter_vm_folder}\"\n" if !vcenter_vm_folder.empty?
406
                end
407

    
408

    
409
                # Create template object
410
                one_t = VCenterDriver::VIHelper.new_one_item(OpenNebula::Template)
411

    
412
                rc = one_t.allocate(t[:one])
413

    
414
                if OpenNebula.is_error?(rc)
415
                    STDOUT.puts "    Error creating template: #{rc.message}\n"
416
                    template.delete_template if template_copy_ref
417
                    next
418
                end
419

    
420
                one_t.info
421

    
422
                ## Add existing disks to template (OPENNEBULA_MANAGED)
423

    
424
                STDOUT.print "\n    The existing disks and networks in the template"\
425
                             " are being imported, \e[96mplease be patient...\e[39m\n"
426

    
427
                template = t[:template] if !template
428

    
429

    
430
                error, template_disks, allocated_images = template.import_vcenter_disks(vc_uuid,
431
                                                                                        dpool,
432
                                                                                        ipool,
433
                                                                                        false,
434
                                                                                        one_t["ID"])
435

    
436
                if error.empty?
437
                    t[:one] << template_disks
438
                else
439
                    STDOUT.puts error
440
                    # Rollback
441
                    template.delete_template if template_copy_ref
442
                    one_t.delete if one_t
443
                    one_t = nil
444
                    next
445
                end
446

    
447
                template_moref = template_copy_ref ? template_copy_ref : t[:vcenter_ref]
448

    
449
                wild = false # We are not importing from a Wild VM
450
                error, template_nics, allocated_nets = template.import_vcenter_nics(vc_uuid,
451
                                                                                    npool,
452
                                                                                    hpool,
453
                                                                                    options[:vcenter],
454
                                                                                    template_moref,
455
                                                                                    wild,
456
                                                                                    false,
457
                                                                                    template["name"],
458
                                                                                    one_t["ID"],
459
                                                                                    dc)
460

    
461
                if error.empty?
462
                    t[:one] << template_nics
463
                else
464
                    STDOUT.puts error
465
                    # Rollback
466
                    allocated_images.each do |i| i.delete end
467
                    allocated_images = []
468
                    template.delete_template if template_copy_ref
469
                    one_t.delete if one_t
470
                    one_t = nil
471
                    next
472
                end
473

    
474
                # Resource Pools
475
                rp_input = ""
476
                rp_split = t[:rp].split("|")
477

    
478
                if !use_defaults
479

    
480
                    if rp_split.size > 3
481
                        STDOUT.print "\n\n    This template is currently set to "\
482
                            "launch VMs in the default resource pool."\
483
                            "\n    Press y to keep this behaviour, n to select"\
484
                            " a new resource pool or d to delegate the choice"\
485
                            " to the user ([y]/n/d)? "
486

    
487
                        answer =  STDIN.gets.strip.downcase
488

    
489
                        case answer
490
                        when 'd'
491
                            list_of_rp   = rp_split[-2]
492
                            default_rp   = rp_split[-1]
493
                            rp_input     = rp_split[0] + "|" + rp_split[1] + "|" +
494
                                            rp_split[2] + "|"
495

    
496
                            # Available list of resource pools
497
                            input_str = "    The list of available resource pools "\
498
                                        "to be presented to the user are "\
499
                                        "\"#{list_of_rp}\""
500
                            input_str+= "\n    Press y to agree, or input a comma"\
501
                                        " separated list of resource pools to edit "\
502
                                        "([y]/comma separated list) "
503
                            STDOUT.print input_str
504

    
505
                            answer = STDIN.gets.strip
506

    
507
                            if !answer.empty? && answer.downcase != 'y'
508
                                rp_input += answer + "|"
509
                            else
510
                                rp_input += rp_split[3] + "|"
511
                            end
512

    
513
                            # Default
514
                            input_str   = "    The default resource pool presented "\
515
                                            "to the end user is set to"\
516
                                            " \"#{default_rp}\"."
517
                            input_str+= "\n    Press y to agree, or input a new "\
518
                                        "resource pool ([y]/resource pool name) "
519
                            STDOUT.print input_str
520

    
521
                            answer = STDIN.gets.strip
522

    
523
                            if !answer.empty? && answer.downcase != 'y'
524
                                rp_input += answer
525
                            else
526
                                rp_input += rp_split[4]
527
                            end
528
                        when 'n'
529

    
530
                            list_of_rp   = rp_split[-2]
531

    
532
                            STDOUT.print "    The list of available resource pools is:\n\n"
533

    
534
                            index = 1
535
                            t[:rp_list].each do |r|
536
                                list_str = "    - #{r[:name]}\n"
537
                                index += 1
538
                                STDOUT.print list_str
539
                            end
540

    
541
                            input_str = "\n    Please input the new default"\
542
                                        " resource pool name: "
543

    
544
                            STDOUT.print input_str
545

    
546
                            answer = STDIN.gets.strip
547

    
548
                            t[:one] << "VCENTER_RESOURCE_POOL=\"#{answer}\"\n"
549
                        end
550
                    end
551
                end
552

    
553
                if !rp_input.empty?
554
                    t[:one] << "USER_INPUTS=["
555
                    t[:one] << "VCENTER_RESOURCE_POOL=\"#{rp_input}\"," if !rp_input.empty?
556
                    t[:one] = t[:one][0..-2]
557
                    t[:one] << "]"
558
                end
559

    
560
                rc = one_t.update(t[:one])
561

    
562
                if OpenNebula.is_error?(rc)
563
                    STDOUT.puts "    Error creating template: #{rc.message}\n"
564

    
565
                    # Rollback
566
                    template.delete_template if template_copy_ref
567
                    allocated_images.each do |i| i.delete end
568
                    allocated_images = []
569
                    allocated_nets.each do |n| n.delete end
570
                    allocated_nets = []
571
                    one_t.delete if one_t
572
                    one_t = nil
573
                else
574
                    STDOUT.puts "\n    OpenNebula template \e[92m#{t[:name]}\e[39m with ID \e[94m#{one_t.id}\e[39m created!\n"
575
                end
576
            }
577
        }
578
    rescue Interrupt => e
579
        puts "\n"
580
        exit 0 #Ctrl+C
581
    rescue Exception => e
582
        STDOUT.puts "There was an error trying to import a vcenter template: #{e.message}/\n#{e.backtrace}"
583

    
584
         # Rollback
585
        allocated_images.each do |i| i.delete end
586
        allocated_images = []
587
        allocated_nets.each do |n| n.delete end
588
        allocated_nets = []
589
        one_t.delete if one_t
590
        template.delete_template if template_copy_ref
591
    ensure
592
        vi_client.close_connection if vi_client
593
    end
594
end
595

    
596
def self.import_networks(con_ops, options)
597
    begin
598
        STDOUT.print "\nConnecting to vCenter: #{options[:vcenter]}..."
599

    
600
        use_defaults = options.key?(:defaults)
601

    
602
        vi_client = VCenterDriver::VIClient.new(con_ops)
603

    
604
        STDOUT.print "done!\n\n"
605

    
606
        STDOUT.print "Looking for vCenter networks..."
607

    
608
        dc_folder = VCenterDriver::DatacenterFolder.new(vi_client)
609

    
610
        # OpenNebula's VirtualNetworkPool
611
        npool = VCenterDriver::VIHelper.one_pool(OpenNebula::VirtualNetworkPool, false)
612
        if npool.respond_to?(:message)
613
            raise "Could not get OpenNebula VirtualNetworkPool: #{npool.message}"
614
        end
615

    
616
        # Get OpenNebula's host pool
617
        hpool = VCenterDriver::VIHelper.one_pool(OpenNebula::HostPool, false)
618
        if hpool.respond_to?(:message)
619
            raise "Could not get OpenNebula HostPool: #{hpool.message}"
620
        end
621

    
622
        rs = dc_folder.get_unimported_networks(npool,options[:vcenter],hpool)
623

    
624
        STDOUT.print "done!\n"
625

    
626
        rs.each {|dc, tmps|
627

    
628
            if !use_defaults
629
                STDOUT.print "\nDo you want to process datacenter #{dc} [y/n]? "
630

    
631
                next if STDIN.gets.strip.downcase != 'y'
632
            end
633

    
634
            if tmps.empty?
635
                STDOUT.print "    No new Networks found in #{dc}...\n\n"
636
                next
637
            end
638

    
639
            tmps.each do |n|
640
                if !use_defaults
641
                    print_str =  "\n  * Network found:\n"\
642
                                 "      - Name                  : \e[92m#{n[:name]}\e[39m\n"\
643
                                 "      - Type                  : #{n[:type]}\n"\
644
                                 "      - Cluster               : \e[96m#{n[:cluster]}\e[39m\n"\
645
                                 "      - Cluster location      : #{n[:cluster_location]}\n"\
646
                                 "      - OpenNebula Cluster ID : #{n[:one_cluster_id]}\n"
647
                    print_str << "    Import this Network (y/[n])? "
648

    
649
                    STDOUT.print print_str
650

    
651
                    next if STDIN.gets.strip.downcase != 'y'
652
                end
653

    
654
                size="255"
655
                ar_type="e"
656
                first_ip=nil
657
                first_mac=nil
658
                slaac=nil
659
                global_prefix=nil
660
                ula_prefix=nil
661
                ip6_address = nil
662
                prefix_length = nil
663

    
664
                # Size
665
                if !use_defaults
666
                    STDOUT.print "    How many VMs are you planning"\
667
                                " to fit into this network [255]? "
668
                    size_answer = STDIN.gets.strip
669
                    if !size_answer.empty?
670
                        size = size_answer.to_i.to_s rescue "255"
671
                    end
672
                end
673

    
674
                # Type
675
                if !use_defaults
676
                    STDOUT.print "    What type of Virtual Network"\
677
                                " do you want to create (IPv[4],IPv[6]"\
678
                                ",[E]thernet)?"
679

    
680
                    type_answer = STDIN.gets.strip
681
                    type_answer = "e" if type_answer.empty?
682
                    if ["4","6","e"].include?(type_answer.downcase)
683
                        ar_type = type_answer.downcase
684
                    else
685
                        ar_type = "e"
686
                        STDOUT.puts "    Type [#{type_answer}] not supported,"\
687
                                    " defaulting to Ethernet."
688
                    end
689

    
690
                    case ar_type.downcase
691
                    when "4"
692
                        STDOUT.print "    Please input the first IP "\
693
                                        "in the range: "
694
                        first_ip = STDIN.gets.strip
695

    
696
                        STDOUT.print "    Please input the first MAC "\
697
                                        "in the range [Enter for default]: "
698
                        mac_answer = STDIN.gets.strip
699
                        first_mac = first_mac_answer if !mac_answer.empty?
700
                    when "6"
701
                        STDOUT.print "    Please input the first MAC "\
702
                                        "in the range [Enter for default]: "
703
                        mac_answer = STDIN.gets.strip
704
                        first_mac = first_mac_answer if !mac_answer.empty?
705

    
706
                        STDOUT.print "    Do you want to use SLAAC "\
707
                                     "Stateless Address Autoconfiguration? ([y]/n): "
708
                        slaac_answer = STDIN.gets.strip.strip.downcase
709

    
710
                        if slaac_answer == 'n'
711
                            slaac = false
712
                            STDOUT.print "    Please input the IPv6 address (cannot be empty): "
713
                            ip6_address = STDIN.gets.strip
714
                            ip6_address = ip6_address if !ip6_address.empty?
715

    
716
                            STDOUT.print "    Please input the Prefix length (cannot be empty): "
717
                            prefix_length = STDIN.gets.strip
718
                            prefix_length = prefix_length if !prefix_length.empty?
719
                        else
720
                            slaac = true
721
                            STDOUT.print "    Please input the GLOBAL PREFIX "\
722
                                        "[Enter for default]: "
723
                            gp_answer = STDIN.gets.strip
724
                            global_prefix = gp_answer if !gp_answer.empty?
725

    
726
                            STDOUT.print "    Please input the ULA PREFIX "\
727
                                            "[Enter for default]: "
728
                            ula_answer = STDIN.gets.strip
729
                            ula_prefix = ula_answer if !ula_answer.empty?
730
                        end
731
                    when "e"
732
                        STDOUT.print "    Please input the first MAC "\
733
                                "in the range [Enter for default]: "
734
                        mac_answer = STDIN.gets.strip
735
                        first_mac = first_mac_answer if !mac_answer.empty?
736
                    end
737
                end
738

    
739
                ar_str =  "\nAR=[TYPE=\""
740

    
741
                case ar_type
742
                when "4"
743
                    ar_str << "IP4\""
744
                    ar_str << ",IP=" + first_ip if first_ip
745
                    ar_str << ",MAC=" + first_mac if first_mac
746
                when "6"
747
                    if slaac
748
                        ar_str << "IP6\""
749
                        ar_str << ",MAC=" + first_mac if first_mac
750
                        ar_str << ",GLOBAL_PREFIX=" + global_prefix if global_prefix
751
                        ar_str << ",ULA_PREFIX=" + ula_prefix if ula_prefix
752
                    else
753
                        ar_str << "IP6_STATIC\""
754
                        ar_str << ",MAC=" + first_mac if first_mac
755
                        ar_str << ",IP6=" + ip6_address if ip6_address
756
                        ar_str << ",PREFIX_LENGTH=" + prefix_length if prefix_length
757
                    end
758
                when "e"
759
                    ar_str << "ETHER\""
760
                    ar_str << ",MAC=" + first_mac if first_mac
761
                end
762

    
763
                ar_str << ",SIZE = \"#{size}\"]"
764

    
765
                n[:one] << ar_str
766

    
767
                one_vn = VCenterDriver::VIHelper.new_one_item(OpenNebula::VirtualNetwork)
768

    
769
                rc = one_vn.allocate(n[:one],n[:one_cluster_id].to_i)
770

    
771
                if ::OpenNebula.is_error?(rc)
772
                    STDOUT.puts "\n    Error creating virtual network: " +
773
                                " #{rc.message}\n"
774
                else
775
                    STDOUT.puts "\n    OpenNebula virtual network \e[92m#{n[:import_name]}\e[39m " +
776
                                "with ID \e[94m#{one_vn.id}\e[39m created with size #{size}!\n"
777
                end
778
            end
779
        }
780
    rescue Interrupt => e
781
        puts "\n"
782
        exit 0 #Ctrl+C
783
    rescue Exception => e
784
        STDOUT.puts "    Error: #{e.message}/\n#{e.backtrace}"
785
    ensure
786
        vi_client.close_connection if vi_client
787
    end
788
end
789

    
790
def self.import_datastore(con_ops, options)
791
    begin
792
        STDOUT.print "\nConnecting to vCenter: #{options[:vcenter]}..."
793

    
794
        use_defaults = options.key?(:defaults)
795

    
796
        vi_client = VCenterDriver::VIClient.new(con_ops)
797

    
798
        STDOUT.print "done!\n\n"
799

    
800
        STDOUT.print "Looking for Datastores..."
801

    
802
        dc_folder = VCenterDriver::DatacenterFolder.new(vi_client)
803

    
804
        dpool = VCenterDriver::VIHelper.one_pool(OpenNebula::DatastorePool, false)
805
        if dpool.respond_to?(:message)
806
            raise "Could not get OpenNebula DatastorePool: #{dpool.message}"
807
        end
808

    
809
        # OpenNebula's HostPool
810
        hpool = VCenterDriver::VIHelper.one_pool(OpenNebula::HostPool, false)
811
        if hpool.respond_to?(:message)
812
            raise "Could not get OpenNebula HostPool: #{hpool.message}"
813
        end
814

    
815
        rs = dc_folder.get_unimported_datastores(dpool, options[:vcenter], hpool)
816

    
817
        STDOUT.print "done!\n"
818

    
819
        rs.each {|dc, tmps|
820
            if !use_defaults
821
                STDOUT.print "\nDo you want to process datacenter \e[95m#{dc}\e[39m (y/[n])? "
822

    
823
                next if STDIN.gets.strip.downcase != 'y'
824
            end
825

    
826
            if tmps.empty?
827
                STDOUT.print "    No new Datastores or StoragePods found in #{dc}...\n\n"
828
                next
829
            end
830

    
831
            tmps.each{ |d|
832
                if !use_defaults
833
                    STDOUT.print "\n  * Datastore found:\n"\
834
                                    "      - Name                  : \e[92m#{d[:simple_name]}\e[39m\n"\
835
                                    "      - Total MB              : #{d[:total_mb]}\n"\
836
                                    "      - Free  MB              : #{d[:free_mb]}\n"\
837
                                    "      - OpenNebula Cluster IDs: #{d[:cluster].join(',')}\n"\
838
                                    "   Import this datastore [y/n]? "
839

    
840
                    next if STDIN.gets.strip.downcase != 'y'
841

    
842
                    STDOUT.print "\n    NOTE: For each vCenter datastore a SYSTEM and IMAGE datastore\n"\
843
                                 "    will be created in OpenNebula except for a StorageDRS which is \n"\
844
                                 "    represented as a SYSTEM datastore only.\n"
845

    
846
                end
847

    
848
                d[:ds].each do |ds|
849
                    one_d = VCenterDriver::VIHelper.new_one_item(OpenNebula::Datastore)
850
                    rc = one_d.allocate(ds[:one])
851
                    if ::OpenNebula.is_error?(rc)
852
                        STDOUT.puts "    \n    Error creating datastore: #{rc.message}"
853
                    else
854
                        # Update template with credentials
855
                        one = ""
856
                        one << "VCENTER_HOST=\"#{con_ops[:host]}\"\n"
857
                        one << "VCENTER_USER=\"#{con_ops[:user]}\"\n"
858
                        one << "VCENTER_PASSWORD=\"#{con_ops[:password]}\"\n"
859

    
860
                        rc = one_d.update(one,true)
861
                        if ::OpenNebula.is_error?(rc)
862
                            STDOUT.puts "    \n    Error updating datastore: \e[91m#{rc.message}\e[39m"
863
                        else
864
                            STDOUT.puts "    \n    OpenNebula datastore \e[92m#{d[:name]}\e[39m with ID \e[94m#{one_d.id}\e[39m created!\n"
865

    
866
                            # Let's add it to clusters
867
                            d[:cluster].each do |cid|
868
                                one_cluster = VCenterDriver::VIHelper.one_item(OpenNebula::Cluster, cid.to_s, false)
869
                                if ::OpenNebula.is_error?(one_cluster)
870
                                    STDOUT.puts "    \n    Error retrieving cluster #{cid}: #{rc.message}"
871
                                end
872
                                rc = one_cluster.adddatastore(one_d.id)
873
                                if ::OpenNebula.is_error?(rc)
874
                                    STDOUT.puts "    \n    Error adding datastore #{one_d.id} to OpenNebula cluster #{cid}: #{rc.message}. You may have to place this datastore in the right cluster by hand"
875
                                end
876
                            end
877

    
878
                            if !d[:cluster].empty?
879
                                one_cluster = VCenterDriver::VIHelper.one_item(OpenNebula::Cluster, "0", false)
880
                                if ::OpenNebula.is_error?(one_cluster)
881
                                    STDOUT.puts "    \n    Error retrieving default cluster: #{rc.message}"
882
                                end
883
                                rc = one_cluster.deldatastore(one_d.id)
884
                                if ::OpenNebula.is_error?(rc)
885
                                    STDOUT.puts "    \n    Error removing datastore #{one_d.id} from default datastore."
886
                                end
887
                            end
888
                        end
889
                    end
890
                end
891
            }
892
        }
893
    rescue Interrupt => e
894
        puts "\n"
895
        exit 0 #Ctrl+C
896
    rescue Exception => e
897
        STDOUT.puts "    Error: #{e.message}/\n#{e.backtrace}"
898
    ensure
899
        vi_client.close_connection if vi_client
900
    end
901
end
902

    
903
def self.import_images(con_ops, ds_name, options)
904

    
905
    begin
906
        STDOUT.print "\nConnecting to vCenter: #{options[:vcenter]}..."
907

    
908
        use_defaults = options.key?(:defaults)
909

    
910
        vi_client = VCenterDriver::VIClient.new(con_ops)
911

    
912
        STDOUT.print "done!\n\n"
913

    
914
        STDOUT.print "Looking for Images..."
915

    
916
        one_ds = VCenterDriver::VIHelper.find_by_name(OpenNebula::DatastorePool,
917
                                                        ds_name)
918
        one_ds_ref = one_ds['TEMPLATE/VCENTER_DS_REF']
919

    
920
        ds = VCenterDriver::Datastore.new_from_ref(one_ds_ref, vi_client)
921
        ds.one_item = one_ds #Store opennebula template for datastore
922
        vc_uuid   = vi_client.vim.serviceContent.about.instanceUuid
923
        one_ds_instance_id = one_ds['TEMPLATE/VCENTER_INSTANCE_ID']
924

    
925
        if one_ds_instance_id != vc_uuid
926
            raise "Datastore is not in the same vCenter instance provided in credentials"
927
        end
928

    
929
        images = ds.get_images
930

    
931
        STDOUT.print "done!\n"
932

    
933
        images.each{ |i|
934

    
935
                if !use_defaults
936
                    STDOUT.print "\n  * Image found:\n"\
937
                                    "      - Name      : #{i[:name]}\n"\
938
                                    "      - Path      : #{i[:path]}\n"\
939
                                    "      - Type      : #{i[:type]}\n"\
940
                                    "      - Size (MB) : #{i[:size]}\n"\
941
                                    "    Import this Image (y/[n])? "
942

    
943
                    next if STDIN.gets.strip.downcase != 'y'
944
                end
945

    
946
                one_i = VCenterDriver::VIHelper.new_one_item(OpenNebula::Image)
947

    
948
                rc = one_i.allocate(i[:one], i[:dsid].to_i)
949

    
950
                if ::OpenNebula.is_error?(rc)
951
                    STDOUT.puts "Error creating image: #{rc.message}\n"
952
                    if rc.message == "[ImageAllocate] Not enough space "\
953
                                        "in datastore"
954
                        STDOUT.puts "Please disable DATASTORE_CAPACITY_"\
955
                                    "CHECK in /etc/one/oned.conf and "\
956
                                    "restart OpenNebula."
957
                    end
958
                else
959
                    STDOUT.puts "    OpenNebula image #{one_i.id} created!\n"
960
                end
961
        }
962
    rescue Interrupt => e
963
        puts "\n"
964
        exit 0 #Ctrl+C
965
    rescue Exception => e
966
        STDOUT.puts "    Error: #{e.message}/\n#{e.backtrace}"
967
    ensure
968
        vi_client.close_connection if vi_client
969
    end
970
end
971

    
972
end # Importer
973

    
974
end # module VCenterDriver