Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (40 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
        rc = one_vm.allocate(template)
57
        return rc if OpenNebula.is_error?(rc)
58

    
59
        rc = one_vm.deploy(host_id, false)
60
        return rc if OpenNebula.is_error?(rc)
61

    
62
        # Set reference to template disks and nics in VM template
63
        vcenter_vm.one_item = one_vm
64
        vcenter_vm.reference_unmanaged_devices(vm_ref)
65

    
66
        # Set vnc configuration F#5074
67
        vnc_port  = one_vm["TEMPLATE/GRAPHICS/PORT"]
68
        elapsed_seconds = 0
69

    
70
        # Let's update the info to gather VNC port
71
        until vnc_port || elapsed_seconds > 30
72
            sleep(1)
73
            one_vm.info
74
            vnc_port  = one_vm["TEMPLATE/GRAPHICS/PORT"]
75
            elapsed_seconds += 1
76
        end
77

    
78
        if vnc_port
79
            vcenter_vm.one_item = one_vm
80
            extraconfig   = []
81
            extraconfig  += vcenter_vm.extraconfig_vnc
82
            spec_hash     = { :extraConfig  => extraconfig }
83
            spec = RbVmomi::VIM.VirtualMachineConfigSpec(spec_hash)
84
            vcenter_vm.item.ReconfigVM_Task(:spec => spec).wait_for_completion
85
        end
86

    
87
        # Add VCENTER_ESX_HOST to MONITOR info so VNC works for running VMs F#4242
88
        esx_host = vcenter_vm["runtime.host.name"].to_s
89
        f = File.open(File.join(VNC_ESX_HOST_FOLDER, "vcenter_vnc_#{one_vm.id}"), 'w')
90
        f.write(esx_host)
91
        f.close
92

    
93
        return one_vm.id
94

    
95
    rescue Exception => e
96
        vi_client.close_connection if vi_client
97
        return OpenNebula::Error.new("#{e.message}/#{e.backtrace}")
98
    end
99
end
100

    
101
def self.import_clusters(con_ops, options)
102
    begin
103
        STDOUT.print "\nConnecting to vCenter: #{options[:vcenter]}..."
104

    
105
        use_defaults = options.key?(:defaults)
106

    
107
        vi_client = VCenterDriver::VIClient.new(con_ops)
108

    
109
        STDOUT.print "done!\n\n"
110

    
111
        STDOUT.print "Exploring vCenter resources..."
112

    
113
        dc_folder = VCenterDriver::DatacenterFolder.new(vi_client)
114

    
115
        vcenter_instance_name = vi_client.vim.host
116
        vc_uuid   = vi_client.vim.serviceContent.about.instanceUuid
117

    
118
        # OpenNebula's ClusterPool
119
        cpool = VCenterDriver::VIHelper.one_pool(OpenNebula::ClusterPool, false)
120
        if cpool.respond_to?(:message)
121
            raise "Could not get OpenNebula ClusterPool: #{cpool.message}"
122
        end
123

    
124
        cluster_list = {}
125
        cpool.each do |c|
126
            cluster_list[c["ID"]] = c["NAME"] if c["ID"].to_i != 0
127
        end
128

    
129
        # Get OpenNebula's host pool
130
        hpool = VCenterDriver::VIHelper.one_pool(OpenNebula::HostPool, false)
131
        if hpool.respond_to?(:message)
132
            raise "Could not get OpenNebula HostPool: #{hpool.message}"
133
        end
134

    
135
        rs = dc_folder.get_unimported_hosts(hpool,vcenter_instance_name)
136

    
137
        STDOUT.print "done!\n\n"
138

    
139
        rs.each {|dc, clusters|
140

    
141
            if !use_defaults
142
                STDOUT.print "Do you want to process datacenter #{dc} (y/[n])? "
143
                next if STDIN.gets.strip.downcase != 'y'
144
            end
145

    
146
            if clusters.empty?
147
                STDOUT.puts "\n    No new clusters found in #{dc}..."
148
                next
149
            end
150

    
151
            clusters.each{ |cluster|
152
                one_cluster_id = nil
153
                rpool = nil
154
                if !use_defaults
155
                    STDOUT.print "\n  * vCenter cluster found:\n"\
156
                                 "      - Name       : \e[92m#{cluster[:simple_name]}\e[39m\n"\
157
                                 "      - Location   : #{cluster[:cluster_location]}\n"\
158
                                 "    Import cluster (y/[n])? "
159
                    next if STDIN.gets.strip.downcase != 'y'
160

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

    
164
                        cluster_list_str = "\n"
165
                        cluster_list.each do |key, value|
166
                            cluster_list_str << "      - \e[94mID: " << key << "\e[39m - NAME: " << value << "\n"
167
                        end
168

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

    
172
                        answer = STDIN.gets.strip
173
                        if !answer.empty?
174
                            one_cluster_id = answer
175
                        end
176
                    end
177

    
178
                    if !one_cluster_id
179
                        one_cluster = VCenterDriver::VIHelper.new_one_item(OpenNebula::Cluster)
180
                        rc = one_cluster.allocate("#{cluster[:cluster_name]}")
181
                        if ::OpenNebula.is_error?(rc)
182
                            STDOUT.puts "    Error creating OpenNebula cluster: #{rc.message}\n"
183
                            next
184
                        end
185
                        one_cluster_id = one_cluster.id
186
                    end
187
                else
188
                    # Defaults, add host to new cluster
189
                    one_cluster = VCenterDriver::VIHelper.new_one_item(OpenNebula::Cluster)
190
                    rc = one_cluster.allocate("#{cluster[:cluster_name]}")
191
                    if ::OpenNebula.is_error?(rc)
192
                        STDOUT.puts "    Error creating OpenNebula cluster: #{rc.message}\n"
193
                        next
194
                    end
195
                    one_cluster_id = one_cluster.id
196
                end
197

    
198

    
199

    
200
                # Generate the template and create the host in the pool
201
                one_host = VCenterDriver::ClusterComputeResource.to_one(cluster,
202
                                                                        con_ops,
203
                                                                        rpool,
204
                                                                        one_cluster_id)
205

    
206
                STDOUT.puts "\n    OpenNebula host \e[92m#{cluster[:cluster_name]}\e[39m with"\
207
                            " ID \e[94m#{one_host.id}\e[39m successfully created."
208
                STDOUT.puts
209
            }
210
        }
211
    rescue Interrupt => e
212
        puts "\n"
213
        exit 0 #Ctrl+C
214
    rescue Exception => e
215
        STDOUT.puts "    Error: #{e.message}/\n#{e.backtrace}"
216
    ensure
217
        vi_client.close_connection if vi_client
218
    end
219

    
220
end
221

    
222
def self.import_templates(con_ops, options)
223
    begin
224
        STDOUT.print "\nConnecting to vCenter: #{options[:vcenter]}..."
225

    
226
        use_defaults = options.key?(:defaults)
227

    
228
        vi_client = VCenterDriver::VIClient.new(con_ops)
229

    
230
        STDOUT.print "done!\n\n"
231

    
232
        STDOUT.print "Looking for VM Templates..."
233

    
234
        dc_folder = VCenterDriver::DatacenterFolder.new(vi_client)
235

    
236
        # Get OpenNebula's templates pool
237
        tpool = VCenterDriver::VIHelper.one_pool(OpenNebula::TemplatePool, false)
238
        if tpool.respond_to?(:message)
239
            raise "Could not get OpenNebula TemplatePool: #{tpool.message}"
240
        end
241

    
242
        rs = dc_folder.get_unimported_templates(vi_client, tpool)
243

    
244
        STDOUT.print "done!\n"
245

    
246
        # Create OpenNebula pools
247
        dpool = VCenterDriver::VIHelper.one_pool(OpenNebula::DatastorePool)
248
        if dpool.respond_to?(:message)
249
            raise "Could not get OpenNebula DatastorePool: #{dpool.message}"
250
        end
251
        ipool = VCenterDriver::VIHelper.one_pool(OpenNebula::ImagePool)
252
        if ipool.respond_to?(:message)
253
            raise "Could not get OpenNebula ImagePool: #{ipool.message}"
254
        end
255
        npool = VCenterDriver::VIHelper.one_pool(OpenNebula::VirtualNetworkPool)
256
        if npool.respond_to?(:message)
257
            raise "Could not get OpenNebula VirtualNetworkPool: #{npool.message}"
258
        end
259
        hpool = VCenterDriver::VIHelper.one_pool(OpenNebula::HostPool)
260
        if hpool.respond_to?(:message)
261
            raise "Could not get OpenNebula HostPool: #{hpool.message}"
262
        end
263

    
264
        # Get vcenter intance uuid as moref is unique for each vcenter
265
        vc_uuid = vi_client.vim.serviceContent.about.instanceUuid
266

    
267
        # Init vars
268
        allocated_images  = []
269
        allocated_nets    = []
270
        one_t             = nil
271
        template_copy_ref = nil
272

    
273
        rs.each {|dc, tmps|
274

    
275
            if !use_defaults
276
                STDOUT.print "\nDo you want to process datacenter #{dc} (y/[n])? "
277
                next if STDIN.gets.strip.downcase != 'y'
278
            end
279

    
280
            if tmps.empty?
281
                STDOUT.print "    No new VM Templates found in #{dc}...\n\n"
282
                next
283
            end
284

    
285
            tmps.each{ |t|
286
                template = nil
287
                template_copy_ref = nil
288

    
289
                if !use_defaults
290
                    STDOUT.print "\n  * VM Template found:\n"\
291
                                    "      - Name       : \e[92m#{t[:template_name]}\e[39m\n"\
292
                                    "      - Cluster    : \e[96m#{t[:cluster_name]}\e[39m\n"\
293
                                    "      - Location   : #{t[:template_location]}\n"\
294
                                    "    Import this VM template (y/[n])? "
295

    
296
                    next if STDIN.gets.strip.downcase != 'y'
297
                end
298

    
299
                allocated_images = []
300
                allocated_nets   = []
301

    
302
                # Linked Clones
303
                if !use_defaults
304

    
305
                    template = VCenterDriver::Template.new_from_ref(t[:vcenter_ref], vi_client)
306

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

    
312
                    if STDIN.gets.strip.downcase == 'y'
313

    
314
                        STDOUT.print "\n    Linked clones requires that delta"\
315
                                     " disks must be created for each disk in the template."\
316
                                     " This operation may change the template contents."\
317
                                     " \n    Do you want OpenNebula to create a copy of the template,"\
318
                                     " so the original template remains untouched ([y]/n)? "
319

    
320
                        template = t[:template]
321
                        if STDIN.gets.strip.downcase != 'n'
322

    
323
                            STDOUT.print "\n    The new template will be named"\
324
                                         " adding a one- prefix to the name"\
325
                                         " of the original template. \n"\
326
                                         "    If you prefer a different name"\
327
                                         " please specify or press Enter"\
328
                                         " to use defaults: "
329

    
330
                            template_name = STDIN.gets.strip.downcase
331

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

    
335

    
336
                            error, template_copy_ref = template.create_template_copy(template_name)
337

    
338
                            if template_copy_ref
339

    
340
                                template = VCenterDriver::Template.new_from_ref(template_copy_ref, vi_client)
341

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

    
344
                                if one_template
345
                                    #Now create delta disks
346
                                    STDOUT.print "\n    Delta disks are being created, please be patient..."
347

    
348
                                    lc_error, use_lc = template.create_delta_disks
349
                                    if lc_error
350
                                        STDOUT.print "\n    ERROR. Something was wrong with the create delta disks on the template operation: #{lc_error}.\n"\
351
                                                    "\n    Linked Clones will not be used with this template.\n"
352
                                    else
353
                                        one_template[:one] << "\nVCENTER_LINKED_CLONES=\"YES\"\n"
354
                                        t = one_template
355
                                    end
356
                                else
357
                                    STDOUT.print "\n    ERROR. Something was wrong obtaining the info from the template's copy.\n"\
358
                                                 "\n    Linked Clones will not be used with this template.\n"
359
                                    template.delete_template if template_copy_ref
360
                                end
361

    
362
                            else
363
                                STDOUT.print "\n    ERROR. #{error}\n"
364
                            end
365

    
366
                        else
367
                            # Create linked clones on top of the existing template
368
                            # Create a VirtualMachine object from the template_copy_ref
369
                            STDOUT.print "\n    Delta disks are being created, \e[96please be patient...\e[39m"
370

    
371
                            lc_error, use_lc = template.create_delta_disks
372
                            if lc_error
373
                                STDOUT.print "\n    ERROR. Something was wrong with the create delta disks on the template operation: #{lc_error}.\n"\
374
                                             "\n    Linked Clones will not be used with this template.\n"
375
                            end
376
                            t[:one] << "\nVCENTER_LINKED_CLONES=\"YES\"\n" if use_lc
377
                        end
378
                    end
379
                end
380

    
381
                vcenter_vm_folder = ""
382
                if !use_defaults
383
                    STDOUT.print "\n\n    Do you want to specify a folder where"\
384
                                    " the deployed VMs based on this template will appear"\
385
                                    " in vSphere's VM and Templates section?"\
386
                                    "\n    If no path is set, VMs will be placed in the same"\
387
                                    " location where the template lives."\
388
                                    "\n    Please specify a path using slashes to separate folders"\
389
                                    " e.g /Management/VMs or press Enter to use defaults: "\
390

    
391
                    vcenter_vm_folder = STDIN.gets.strip
392
                    t[:one] << "VCENTER_VM_FOLDER=\"#{vcenter_vm_folder}\"\n" if !vcenter_vm_folder.empty?
393
                end
394

    
395

    
396
                # Create template object
397
                one_t = VCenterDriver::VIHelper.new_one_item(OpenNebula::Template)
398

    
399
                rc = one_t.allocate(t[:one])
400

    
401
                if OpenNebula.is_error?(rc)
402
                    STDOUT.puts "    Error creating template: #{rc.message}\n"
403
                    template.delete_template if template_copy_ref
404
                    next
405
                end
406

    
407
                one_t.info
408

    
409
                ## Add existing disks to template (OPENNEBULA_MANAGED)
410

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

    
414
                template = t[:template] if !template
415

    
416

    
417
                error, template_disks, allocated_images = template.import_vcenter_disks(vc_uuid,
418
                                                                                        dpool,
419
                                                                                        ipool,
420
                                                                                        false,
421
                                                                                        one_t["ID"])
422

    
423
                if error.empty?
424
                    t[:one] << template_disks
425
                else
426
                    STDOUT.puts error
427
                    # Rollback
428
                    template.delete_template if template_copy_ref
429
                    one_t.delete if one_t
430
                    one_t = nil
431
                    next
432
                end
433

    
434
                template_moref = template_copy_ref ? template_copy_ref : t[:vcenter_ref]
435

    
436
                wild = false # We are not importing from a Wild VM
437
                error, template_nics, allocated_nets = template.import_vcenter_nics(vc_uuid,
438
                                                                                    npool,
439
                                                                                    hpool,
440
                                                                                    options[:vcenter],
441
                                                                                    template_moref,
442
                                                                                    wild,
443
                                                                                    false,
444
                                                                                    template["name"],
445
                                                                                    one_t["ID"],
446
                                                                                    dc)
447

    
448
                if error.empty?
449
                    t[:one] << template_nics
450
                else
451
                    STDOUT.puts error
452
                    # Rollback
453
                    allocated_images.each do |i| i.delete end
454
                    allocated_images = []
455
                    template.delete_template if template_copy_ref
456
                    one_t.delete if one_t
457
                    one_t = nil
458
                    next
459
                end
460

    
461
                # Resource Pools
462
                rp_input = ""
463
                rp_split = t[:rp].split("|")
464

    
465
                if !use_defaults
466

    
467
                    if rp_split.size > 3
468
                        STDOUT.print "\n\n    This template is currently set to "\
469
                            "launch VMs in the default resource pool."\
470
                            "\n    Press y to keep this behaviour, n to select"\
471
                            " a new resource pool or d to delegate the choice"\
472
                            " to the user ([y]/n/d)? "
473

    
474
                        answer =  STDIN.gets.strip.downcase
475

    
476
                        case answer
477
                        when 'd'
478
                            list_of_rp   = rp_split[-2]
479
                            default_rp   = rp_split[-1]
480
                            rp_input     = rp_split[0] + "|" + rp_split[1] + "|" +
481
                                            rp_split[2] + "|"
482

    
483
                            # Available list of resource pools
484
                            input_str = "    The list of available resource pools "\
485
                                        "to be presented to the user are "\
486
                                        "\"#{list_of_rp}\""
487
                            input_str+= "\n    Press y to agree, or input a comma"\
488
                                        " separated list of resource pools to edit "\
489
                                        "([y]/comma separated list) "
490
                            STDOUT.print input_str
491

    
492
                            answer = STDIN.gets.strip
493

    
494
                            if !answer.empty? && answer.downcase != 'y'
495
                                rp_input += answer + "|"
496
                            else
497
                                rp_input += rp_split[3] + "|"
498
                            end
499

    
500
                            # Default
501
                            input_str   = "    The default resource pool presented "\
502
                                            "to the end user is set to"\
503
                                            " \"#{default_rp}\"."
504
                            input_str+= "\n    Press y to agree, or input a new "\
505
                                        "resource pool ([y]/resource pool name) "
506
                            STDOUT.print input_str
507

    
508
                            answer = STDIN.gets.strip
509

    
510
                            if !answer.empty? && answer.downcase != 'y'
511
                                rp_input += answer
512
                            else
513
                                rp_input += rp_split[4]
514
                            end
515
                        when 'n'
516

    
517
                            list_of_rp   = rp_split[-2]
518

    
519
                            STDOUT.print "    The list of available resource pools is:\n\n"
520

    
521
                            index = 1
522
                            t[:rp_list].each do |r|
523
                                list_str = "    - #{r[:name]}\n"
524
                                index += 1
525
                                STDOUT.print list_str
526
                            end
527

    
528
                            input_str = "\n    Please input the new default"\
529
                                        " resource pool name: "
530

    
531
                            STDOUT.print input_str
532

    
533
                            answer = STDIN.gets.strip
534

    
535
                            t[:one] << "VCENTER_RESOURCE_POOL=\"#{answer}\"\n"
536
                        end
537
                    end
538
                end
539

    
540
                if !rp_input.empty?
541
                    t[:one] << "USER_INPUTS=["
542
                    t[:one] << "VCENTER_RESOURCE_POOL=\"#{rp_input}\"," if !rp_input.empty?
543
                    t[:one] = t[:one][0..-2]
544
                    t[:one] << "]"
545
                end
546

    
547
                rc = one_t.update(t[:one])
548

    
549
                if OpenNebula.is_error?(rc)
550
                    STDOUT.puts "    Error creating template: #{rc.message}\n"
551

    
552
                    # Rollback
553
                    template.delete_template if template_copy_ref
554
                    allocated_images.each do |i| i.delete end
555
                    allocated_images = []
556
                    allocated_nets.each do |n| n.delete end
557
                    allocated_nets = []
558
                    one_t.delete if one_t
559
                    one_t = nil
560
                else
561
                    STDOUT.puts "\n    OpenNebula template \e[92m#{t[:name]}\e[39m with ID \e[94m#{one_t.id}\e[39m created!\n"
562
                end
563
            }
564
        }
565
    rescue Interrupt => e
566
        puts "\n"
567
        exit 0 #Ctrl+C
568
    rescue Exception => e
569
        STDOUT.puts "There was an error trying to import a vcenter template: #{e.message}/\n#{e.backtrace}"
570

    
571
         # Rollback
572
        allocated_images.each do |i| i.delete end
573
        allocated_images = []
574
        allocated_nets.each do |n| n.delete end
575
        allocated_nets = []
576
        one_t.delete if one_t
577
        template.delete_template if template_copy_ref
578
    ensure
579
        vi_client.close_connection if vi_client
580
    end
581
end
582

    
583
def self.import_networks(con_ops, options)
584
    begin
585
        STDOUT.print "\nConnecting to vCenter: #{options[:vcenter]}..."
586

    
587
        use_defaults = options.key?(:defaults)
588

    
589
        vi_client = VCenterDriver::VIClient.new(con_ops)
590

    
591
        STDOUT.print "done!\n\n"
592

    
593
        STDOUT.print "Looking for vCenter networks..."
594

    
595
        dc_folder = VCenterDriver::DatacenterFolder.new(vi_client)
596

    
597
        # OpenNebula's VirtualNetworkPool
598
        npool = VCenterDriver::VIHelper.one_pool(OpenNebula::VirtualNetworkPool, false)
599
        if npool.respond_to?(:message)
600
            raise "Could not get OpenNebula VirtualNetworkPool: #{npool.message}"
601
        end
602

    
603
        # Get OpenNebula's host pool
604
        hpool = VCenterDriver::VIHelper.one_pool(OpenNebula::HostPool, false)
605
        if hpool.respond_to?(:message)
606
            raise "Could not get OpenNebula HostPool: #{hpool.message}"
607
        end
608

    
609
        rs = dc_folder.get_unimported_networks(npool,options[:vcenter],hpool)
610

    
611
        STDOUT.print "done!\n"
612

    
613
        rs.each {|dc, tmps|
614

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

    
618
                next if STDIN.gets.strip.downcase != 'y'
619
            end
620

    
621
            if tmps.empty?
622
                STDOUT.print "    No new Networks found in #{dc}...\n\n"
623
                next
624
            end
625

    
626
            tmps.each do |n|
627
                if !use_defaults
628
                    print_str =  "\n  * Network found:\n"\
629
                                 "      - Name                  : \e[92m#{n[:name]}\e[39m\n"\
630
                                 "      - Type                  : #{n[:type]}\n"\
631
                                 "      - Cluster               : \e[96m#{n[:cluster]}\e[39m\n"\
632
                                 "      - Cluster location      : #{n[:cluster_location]}\n"\
633
                                 "      - OpenNebula Cluster ID : #{n[:one_cluster_id]}\n"
634
                    print_str << "    Import this Network (y/[n])? "
635

    
636
                    STDOUT.print print_str
637

    
638
                    next if STDIN.gets.strip.downcase != 'y'
639
                end
640

    
641
                size="255"
642
                ar_type="e"
643
                first_ip=nil
644
                first_mac=nil
645
                slaac=nil
646
                global_prefix=nil
647
                ula_prefix=nil
648
                ip6_address = nil
649
                prefix_length = nil
650

    
651
                # Size
652
                if !use_defaults
653
                    STDOUT.print "    How many VMs are you planning"\
654
                                " to fit into this network [255]? "
655
                    size_answer = STDIN.gets.strip
656
                    if !size_answer.empty?
657
                        size = size_answer.to_i.to_s rescue "255"
658
                    end
659
                end
660

    
661
                # Type
662
                if !use_defaults
663
                    STDOUT.print "    What type of Virtual Network"\
664
                                " do you want to create (IPv[4],IPv[6]"\
665
                                ",[E]thernet)?"
666

    
667
                    type_answer = STDIN.gets.strip
668
                    type_answer = "e" if type_answer.empty?
669
                    if ["4","6","e"].include?(type_answer.downcase)
670
                        ar_type = type_answer.downcase
671
                    else
672
                        ar_type = "e"
673
                        STDOUT.puts "    Type [#{type_answer}] not supported,"\
674
                                    " defaulting to Ethernet."
675
                    end
676

    
677
                    case ar_type.downcase
678
                    when "4"
679
                        STDOUT.print "    Please input the first IP "\
680
                                        "in the range: "
681
                        first_ip = STDIN.gets.strip
682

    
683
                        STDOUT.print "    Please input the first MAC "\
684
                                        "in the range [Enter for default]: "
685
                        mac_answer = STDIN.gets.strip
686
                        first_mac = first_mac_answer if !mac_answer.empty?
687
                    when "6"
688
                        STDOUT.print "    Please input the first MAC "\
689
                                        "in the range [Enter for default]: "
690
                        mac_answer = STDIN.gets.strip
691
                        first_mac = first_mac_answer if !mac_answer.empty?
692

    
693
                        STDOUT.print "    Do you want to use SLAAC "\
694
                                     "Stateless Address Autoconfiguration? ([y]/n): "
695
                        slaac_answer = STDIN.gets.strip.strip.downcase
696

    
697
                        if slaac_answer == 'n'
698
                            slaac = false
699
                            STDOUT.print "    Please input the IPv6 address (cannot be empty): "
700
                            ip6_address = STDIN.gets.strip
701
                            ip6_address = ip6_address if !ip6_address.empty?
702

    
703
                            STDOUT.print "    Please input the Prefix length (cannot be empty): "
704
                            prefix_length = STDIN.gets.strip
705
                            prefix_length = prefix_length if !prefix_length.empty?
706
                        else
707
                            slaac = true
708
                            STDOUT.print "    Please input the GLOBAL PREFIX "\
709
                                        "[Enter for default]: "
710
                            gp_answer = STDIN.gets.strip
711
                            global_prefix = gp_answer if !gp_answer.empty?
712

    
713
                            STDOUT.print "    Please input the ULA PREFIX "\
714
                                            "[Enter for default]: "
715
                            ula_answer = STDIN.gets.strip
716
                            ula_prefix = ula_answer if !ula_answer.empty?
717
                        end
718
                    when "e"
719
                        STDOUT.print "    Please input the first MAC "\
720
                                "in the range [Enter for default]: "
721
                        mac_answer = STDIN.gets.strip
722
                        first_mac = first_mac_answer if !mac_answer.empty?
723
                    end
724
                end
725

    
726
                ar_str =  "\nAR=[TYPE=\""
727

    
728
                case ar_type
729
                when "4"
730
                    ar_str << "IP4\""
731
                    ar_str << ",IP=" + first_ip if first_ip
732
                    ar_str << ",MAC=" + first_mac if first_mac
733
                when "6"
734
                    if slaac
735
                        ar_str << "IP6\""
736
                        ar_str << ",MAC=" + first_mac if first_mac
737
                        ar_str << ",GLOBAL_PREFIX=" + global_prefix if global_prefix
738
                        ar_str << ",ULA_PREFIX=" + ula_prefix if ula_prefix
739
                    else
740
                        ar_str << "IP6_STATIC\""
741
                        ar_str << ",MAC=" + first_mac if first_mac
742
                        ar_str << ",IP6=" + ip6_address if ip6_address
743
                        ar_str << ",PREFIX_LENGTH=" + prefix_length if prefix_length
744
                    end
745
                when "e"
746
                    ar_str << "ETHER\""
747
                    ar_str << ",MAC=" + first_mac if first_mac
748
                end
749

    
750
                ar_str << ",SIZE = \"#{size}\"]"
751

    
752
                n[:one] << ar_str
753

    
754
                one_vn = VCenterDriver::VIHelper.new_one_item(OpenNebula::VirtualNetwork)
755

    
756
                rc = one_vn.allocate(n[:one],n[:one_cluster_id].to_i)
757

    
758
                if ::OpenNebula.is_error?(rc)
759
                    STDOUT.puts "\n    Error creating virtual network: " +
760
                                " #{rc.message}\n"
761
                else
762
                    STDOUT.puts "\n    OpenNebula virtual network \e[92m#{n[:import_name]}\e[39m " +
763
                                "with ID \e[94m#{one_vn.id}\e[39m created with size #{size}!\n"
764
                end
765
            end
766
        }
767
    rescue Interrupt => e
768
        puts "\n"
769
        exit 0 #Ctrl+C
770
    rescue Exception => e
771
        STDOUT.puts "    Error: #{e.message}/\n#{e.backtrace}"
772
    ensure
773
        vi_client.close_connection if vi_client
774
    end
775
end
776

    
777
def self.import_datastore(con_ops, options)
778
    begin
779
        STDOUT.print "\nConnecting to vCenter: #{options[:vcenter]}..."
780

    
781
        use_defaults = options.key?(:defaults)
782

    
783
        vi_client = VCenterDriver::VIClient.new(con_ops)
784

    
785
        STDOUT.print "done!\n\n"
786

    
787
        STDOUT.print "Looking for Datastores..."
788

    
789
        dc_folder = VCenterDriver::DatacenterFolder.new(vi_client)
790

    
791
        dpool = VCenterDriver::VIHelper.one_pool(OpenNebula::DatastorePool, false)
792
        if dpool.respond_to?(:message)
793
            raise "Could not get OpenNebula DatastorePool: #{dpool.message}"
794
        end
795

    
796
        # OpenNebula's HostPool
797
        hpool = VCenterDriver::VIHelper.one_pool(OpenNebula::HostPool, false)
798
        if hpool.respond_to?(:message)
799
            raise "Could not get OpenNebula HostPool: #{hpool.message}"
800
        end
801

    
802
        rs = dc_folder.get_unimported_datastores(dpool, options[:vcenter], hpool)
803

    
804
        STDOUT.print "done!\n"
805

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

    
810
                next if STDIN.gets.strip.downcase != 'y'
811
            end
812

    
813
            if tmps.empty?
814
                STDOUT.print "    No new Datastores or StoragePods found in #{dc}...\n\n"
815
                next
816
            end
817

    
818
            tmps.each{ |d|
819
                if !use_defaults
820
                    STDOUT.print "\n  * Datastore found:\n"\
821
                                    "      - Name                  : \e[92m#{d[:simple_name]}\e[39m\n"\
822
                                    "      - Total MB              : #{d[:total_mb]}\n"\
823
                                    "      - Free  MB              : #{d[:free_mb]}\n"\
824
                                    "      - OpenNebula Cluster IDs: #{d[:cluster].join(',')}\n"\
825
                                    "   Import this datastore [y/n]? "
826

    
827
                    next if STDIN.gets.strip.downcase != 'y'
828

    
829
                    STDOUT.print "\n    NOTE: For each vCenter datastore a SYSTEM and IMAGE datastore\n"\
830
                                 "    will be created in OpenNebula except for a StorageDRS which is \n"\
831
                                 "    represented as a SYSTEM datastore only.\n"
832

    
833
                end
834

    
835
                d[:ds].each do |ds|
836
                    one_d = VCenterDriver::VIHelper.new_one_item(OpenNebula::Datastore)
837
                    rc = one_d.allocate(ds[:one])
838
                    if ::OpenNebula.is_error?(rc)
839
                        STDOUT.puts "    \n    Error creating datastore: #{rc.message}"
840
                    else
841
                        # Update template with credentials
842
                        one = ""
843
                        one << "VCENTER_HOST=\"#{con_ops[:host]}\"\n"
844
                        one << "VCENTER_USER=\"#{con_ops[:user]}\"\n"
845
                        one << "VCENTER_PASSWORD=\"#{con_ops[:password]}\"\n"
846

    
847
                        rc = one_d.update(one,true)
848
                        if ::OpenNebula.is_error?(rc)
849
                            STDOUT.puts "    \n    Error updating datastore: \e[91m#{rc.message}\e[39m"
850
                        else
851
                            STDOUT.puts "    \n    OpenNebula datastore \e[92m#{d[:name]}\e[39m with ID \e[94m#{one_d.id}\e[39m created!\n"
852

    
853
                            # Let's add it to clusters
854
                            d[:cluster].each do |cid|
855
                                one_cluster = VCenterDriver::VIHelper.one_item(OpenNebula::Cluster, cid.to_s, false)
856
                                if ::OpenNebula.is_error?(one_cluster)
857
                                    STDOUT.puts "    \n    Error retrieving cluster #{cid}: #{rc.message}"
858
                                end
859
                                rc = one_cluster.adddatastore(one_d.id)
860
                                if ::OpenNebula.is_error?(rc)
861
                                    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"
862
                                end
863
                            end
864

    
865
                            if !d[:cluster].empty?
866
                                one_cluster = VCenterDriver::VIHelper.one_item(OpenNebula::Cluster, "0", false)
867
                                if ::OpenNebula.is_error?(one_cluster)
868
                                    STDOUT.puts "    \n    Error retrieving default cluster: #{rc.message}"
869
                                end
870
                                rc = one_cluster.deldatastore(one_d.id)
871
                                if ::OpenNebula.is_error?(rc)
872
                                    STDOUT.puts "    \n    Error removing datastore #{one_d.id} from default datastore."
873
                                end
874
                            end
875
                        end
876
                    end
877
                end
878
            }
879
        }
880
    rescue Interrupt => e
881
        puts "\n"
882
        exit 0 #Ctrl+C
883
    rescue Exception => e
884
        STDOUT.puts "    Error: #{e.message}/\n#{e.backtrace}"
885
    ensure
886
        vi_client.close_connection if vi_client
887
    end
888
end
889

    
890
def self.import_images(con_ops, ds_name, options)
891

    
892
    begin
893
        STDOUT.print "\nConnecting to vCenter: #{options[:vcenter]}..."
894

    
895
        use_defaults = options.key?(:defaults)
896

    
897
        vi_client = VCenterDriver::VIClient.new(con_ops)
898

    
899
        STDOUT.print "done!\n\n"
900

    
901
        STDOUT.print "Looking for Images..."
902

    
903
        one_ds = VCenterDriver::VIHelper.find_by_name(OpenNebula::DatastorePool,
904
                                                        ds_name)
905
        one_ds_ref = one_ds['TEMPLATE/VCENTER_DS_REF']
906

    
907
        ds = VCenterDriver::Datastore.new_from_ref(one_ds_ref, vi_client)
908
        ds.one_item = one_ds #Store opennebula template for datastore
909
        vc_uuid   = vi_client.vim.serviceContent.about.instanceUuid
910
        one_ds_instance_id = one_ds['TEMPLATE/VCENTER_INSTANCE_ID']
911

    
912
        if one_ds_instance_id != vc_uuid
913
            raise "Datastore is not in the same vCenter instance provided in credentials"
914
        end
915

    
916
        images = ds.get_images
917

    
918
        STDOUT.print "done!\n"
919

    
920
        images.each{ |i|
921

    
922
                if !use_defaults
923
                    STDOUT.print "\n  * Image found:\n"\
924
                                    "      - Name      : #{i[:name]}\n"\
925
                                    "      - Path      : #{i[:path]}\n"\
926
                                    "      - Type      : #{i[:type]}\n"\
927
                                    "      - Size (MB) : #{i[:size]}\n"\
928
                                    "    Import this Image (y/[n])? "
929

    
930
                    next if STDIN.gets.strip.downcase != 'y'
931
                end
932

    
933
                one_i = VCenterDriver::VIHelper.new_one_item(OpenNebula::Image)
934

    
935
                rc = one_i.allocate(i[:one], i[:dsid].to_i)
936

    
937
                if ::OpenNebula.is_error?(rc)
938
                    STDOUT.puts "Error creating image: #{rc.message}\n"
939
                    if rc.message == "[ImageAllocate] Not enough space "\
940
                                        "in datastore"
941
                        STDOUT.puts "Please disable DATASTORE_CAPACITY_"\
942
                                    "CHECK in /etc/one/oned.conf and "\
943
                                    "restart OpenNebula."
944
                    end
945
                else
946
                    STDOUT.puts "    OpenNebula image #{one_i.id} created!\n"
947
                end
948
        }
949
    rescue Interrupt => e
950
        puts "\n"
951
        exit 0 #Ctrl+C
952
    rescue Exception => e
953
        STDOUT.puts "    Error: #{e.message}/\n#{e.backtrace}"
954
    ensure
955
        vi_client.close_connection if vi_client
956
    end
957
end
958

    
959
end # Importer
960

    
961
end # module VCenterDriver