Statistics
| Branch: | Tag: | Revision:

one / src / vmm_mad / remotes / lib / vcenter_driver / importer.rb @ 0492da97

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
        begin
61
            ds_one = dpool.select do |e|
62
                e["TEMPLATE/TYPE"]                == "SYSTEM_DS" &&
63
                e["TEMPLATE/VCENTER_DS_REF"]      == ds_ref &&
64
                e["TEMPLATE/VCENTER_DC_REF"]      == dc_ref &&
65
                e["TEMPLATE/VCENTER_INSTANCE_ID"] == vc_uuid
66
            end.first
67
        rescue
68
            raise "DS with ref #{ds_ref} is not imported in OpenNebula, aborting Wild VM import."
69
        end
70

    
71
        rc = one_vm.allocate(template)
72
        return rc if OpenNebula.is_error?(rc)
73

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

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

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

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

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

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

    
108
        return one_vm.id
109

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

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

    
120
        use_defaults = options.key?(:defaults)
121

    
122
        vi_client = VCenterDriver::VIClient.new(con_ops)
123

    
124
        STDOUT.print "done!\n\n"
125

    
126
        STDOUT.print "Exploring vCenter resources..."
127

    
128
        dc_folder = VCenterDriver::DatacenterFolder.new(vi_client)
129

    
130
        vcenter_instance_name = vi_client.vim.host
131
        vc_uuid   = vi_client.vim.serviceContent.about.instanceUuid
132

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

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

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

    
150
        rs = dc_folder.get_unimported_hosts(hpool,vcenter_instance_name)
151

    
152
        STDOUT.print "done!\n\n"
153

    
154
        rs.each {|dc, clusters|
155

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

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

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

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

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

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

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

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

    
213

    
214

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

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

    
235
end
236

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

    
241
        use_defaults = options.key?(:defaults)
242

    
243
        vi_client = VCenterDriver::VIClient.new(con_ops)
244

    
245
        STDOUT.print "done!\n\n"
246

    
247
        STDOUT.print "Looking for VM Templates..."
248

    
249
        dc_folder = VCenterDriver::DatacenterFolder.new(vi_client)
250

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

    
257
        rs = dc_folder.get_unimported_templates(vi_client, tpool)
258

    
259
        STDOUT.print "done!\n"
260

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

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

    
282
        # Init vars
283
        allocated_images  = []
284
        allocated_nets    = []
285
        one_t             = nil
286
        template_copy_ref = nil
287

    
288
        rs.each {|dc, tmps|
289

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

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

    
300
            tmps.each{ |t|
301
                template = nil
302
                template_copy_ref = nil
303

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

    
311
                    next if STDIN.gets.strip.downcase != 'y'
312
                end
313

    
314
                allocated_images = []
315
                allocated_nets   = []
316

    
317
                # Linked Clones
318
                if !use_defaults
319

    
320
                    template = VCenterDriver::Template.new_from_ref(t[:vcenter_ref], vi_client)
321

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

    
327
                    if STDIN.gets.strip.downcase == 'y'
328

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

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

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

    
345
                            template_name = STDIN.gets.strip.downcase
346

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

    
350

    
351
                            error, template_copy_ref = template.create_template_copy(template_name)
352

    
353
                            if template_copy_ref
354

    
355
                                template = VCenterDriver::Template.new_from_ref(template_copy_ref, vi_client)
356

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

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

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

    
377
                            else
378
                                STDOUT.print "\n    ERROR. #{error}\n"
379
                            end
380

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

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

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

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

    
410

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

    
414
                rc = one_t.allocate(t[:one])
415

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

    
422
                one_t.info
423

    
424
                ## Add existing disks to template (OPENNEBULA_MANAGED)
425

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

    
429
                template = t[:template] if !template
430

    
431

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

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

    
449
                template_moref = template_copy_ref ? template_copy_ref : t[:vcenter_ref]
450

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

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

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

    
480
                if !use_defaults
481

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

    
489
                        answer =  STDIN.gets.strip.downcase
490

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

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

    
507
                            answer = STDIN.gets.strip
508

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

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

    
523
                            answer = STDIN.gets.strip
524

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

    
532
                            list_of_rp   = rp_split[-2]
533

    
534
                            STDOUT.print "    The list of available resource pools is:\n\n"
535

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

    
543
                            input_str = "\n    Please input the new default"\
544
                                        " resource pool name: "
545

    
546
                            STDOUT.print input_str
547

    
548
                            answer = STDIN.gets.strip
549

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

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

    
562
                rc = one_t.update(t[:one])
563

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

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

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

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

    
602
        use_defaults = options.key?(:defaults)
603

    
604
        vi_client = VCenterDriver::VIClient.new(con_ops)
605

    
606
        STDOUT.print "done!\n\n"
607

    
608
        STDOUT.print "Looking for vCenter networks..."
609

    
610
        dc_folder = VCenterDriver::DatacenterFolder.new(vi_client)
611

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

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

    
624
        rs = dc_folder.get_unimported_networks(npool,options[:vcenter],hpool)
625

    
626
        STDOUT.print "done!\n"
627

    
628
        rs.each {|dc, tmps|
629

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

    
633
                next if STDIN.gets.strip.downcase != 'y'
634
            end
635

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

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

    
651
                    STDOUT.print print_str
652

    
653
                    next if STDIN.gets.strip.downcase != 'y'
654
                end
655

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

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

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

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

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

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

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

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

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

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

    
741
                ar_str =  "\nAR=[TYPE=\""
742

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

    
765
                ar_str << ",SIZE = \"#{size}\"]"
766

    
767
                n[:one] << ar_str
768

    
769
                one_vn = VCenterDriver::VIHelper.new_one_item(OpenNebula::VirtualNetwork)
770

    
771
                rc = one_vn.allocate(n[:one],n[:one_cluster_id].to_i)
772

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

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

    
796
        use_defaults = options.key?(:defaults)
797

    
798
        vi_client = VCenterDriver::VIClient.new(con_ops)
799

    
800
        STDOUT.print "done!\n\n"
801

    
802
        STDOUT.print "Looking for Datastores..."
803

    
804
        dc_folder = VCenterDriver::DatacenterFolder.new(vi_client)
805

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

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

    
817
        rs = dc_folder.get_unimported_datastores(dpool, options[:vcenter], hpool)
818

    
819
        STDOUT.print "done!\n"
820

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

    
825
                next if STDIN.gets.strip.downcase != 'y'
826
            end
827

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

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

    
842
                    next if STDIN.gets.strip.downcase != 'y'
843

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

    
848
                end
849

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

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

    
868
                            # Let's add it to clusters
869
                            d[:cluster].each do |cid|
870
                                one_cluster = VCenterDriver::VIHelper.one_item(OpenNebula::Cluster, cid.to_s, false)
871
                                if ::OpenNebula.is_error?(one_cluster)
872
                                    STDOUT.puts "    \n    Error retrieving cluster #{cid}: #{rc.message}"
873
                                end
874
                                rc = one_cluster.adddatastore(one_d.id)
875
                                if ::OpenNebula.is_error?(rc)
876
                                    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"
877
                                end
878
                            end
879

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

    
905
def self.import_images(con_ops, ds_name, options)
906

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

    
910
        use_defaults = options.key?(:defaults)
911

    
912
        vi_client = VCenterDriver::VIClient.new(con_ops)
913

    
914
        STDOUT.print "done!\n\n"
915

    
916
        STDOUT.print "Looking for Images..."
917

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

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

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

    
931
        images = ds.get_images
932

    
933
        STDOUT.print "done!\n"
934

    
935
        images.each{ |i|
936

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

    
945
                    next if STDIN.gets.strip.downcase != 'y'
946
                end
947

    
948
                one_i = VCenterDriver::VIHelper.new_one_item(OpenNebula::Image)
949

    
950
                rc = one_i.allocate(i[:one], i[:dsid].to_i)
951

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

    
974
end # Importer
975

    
976
end # module VCenterDriver