Class: CloudstackClient::Connection

Inherits:
Object
  • Object
show all
Defined in:
lib/knife-cloudstack/connection.rb

Constant Summary collapse

ASYNC_POLL_INTERVAL =
5.0
ASYNC_TIMEOUT =
600

Instance Method Summary collapse

Constructor Details

#initialize(api_url, api_key, secret_key, project_name = nil, no_ssl_verify = false, api_proxy = nil) ⇒ Connection

Returns a new instance of Connection.



56
57
58
59
60
61
62
63
# File 'lib/knife-cloudstack/connection.rb', line 56

def initialize(api_url, api_key, secret_key, project_name=nil, no_ssl_verify=false, api_proxy=nil)
  @api_url = api_url
  @api_key = api_key
  @secret_key = secret_key
  @no_ssl_verify = no_ssl_verify
  @project_id = get_project_id(project_name) if project_name || nil
  @api_proxy = api_proxy
end

Instance Method Details

#add_nic_to_vm(network_id, server_id, ipaddr = nil) ⇒ Object



655
656
657
658
659
660
661
662
663
664
665
666
667
668
# File 'lib/knife-cloudstack/connection.rb', line 655

def add_nic_to_vm(network_id, server_id, ipaddr=nil)
  params = {
    'command' => 'addNicToVirtualMachine',
    'networkid' => network_id,
    'virtualmachineid' => server_id,
  }

  unless ipaddr.nil?
    params['ipaddress'] = ipaddr
  end

  json = send_async_request(params)
  json['virtualmachine']
end

#associate_ip_address(zone_id, networks) ⇒ Object

Acquires and associates a public IP to an account.



733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
# File 'lib/knife-cloudstack/connection.rb', line 733

def associate_ip_address(zone_id, networks)
  params = {
      'command' => 'associateIpAddress',
      'zoneId' => zone_id
  }
  #Choose the first network from the list
  if networks.nil? || networks.empty?
    default_network = get_default_network(zone_id)
    params['networkId'] = default_network['id']
  else
    params['networkId'] = get_network(networks.first)['id']
  end
  Chef::Log.debug("associate ip params: #{params}")
  json = send_async_request(params)
  json['ipaddress']
end

#create_firewall_rule(ipaddress_id, protocol, param3, param4, cidr_list) ⇒ Object



779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
# File 'lib/knife-cloudstack/connection.rb', line 779

def create_firewall_rule(ipaddress_id, protocol, param3, param4, cidr_list)
  if protocol == "ICMP"
    params = {
      'command' => 'createFirewallRule',
      'ipaddressId' => ipaddress_id,
      'protocol' => protocol,
      'icmptype' =>  param3,
      'icmpcode' => param4,
      'cidrlist' => cidr_list
    }
  else
    params = {
      'command' => 'createFirewallRule',
      'ipaddressId' => ipaddress_id,
      'protocol' => protocol,
      'startport' =>  param3,
      'endport' => param4,
      'cidrlist' => cidr_list
    }
  end
  send_async_request(params)
end

#create_ip_fwd_rule(ipaddress_id, protocol, start_port, end_port) ⇒ Object



767
768
769
770
771
772
773
774
775
776
777
# File 'lib/knife-cloudstack/connection.rb', line 767

def create_ip_fwd_rule(ipaddress_id, protocol, start_port, end_port)
  params = {
    'command' => 'createIpForwardingRule',
    'ipaddressId' => ipaddress_id,
    'protocol' => protocol,
    'startport' =>  start_port,
    'endport' => end_port
  }

  send_async_request(params)
end

#create_port_forwarding_rule(ip_address_id, private_port, protocol, public_port, virtual_machine_id) ⇒ Object

Creates a port forwarding rule.



856
857
858
859
860
861
862
863
864
865
866
867
# File 'lib/knife-cloudstack/connection.rb', line 856

def create_port_forwarding_rule(ip_address_id, private_port, protocol, public_port, virtual_machine_id)
  params = {
      'command' => 'createPortForwardingRule',
      'ipAddressId' => ip_address_id,
      'privatePort' => private_port,
      'protocol' => protocol,
      'publicPort' => public_port,
      'virtualMachineId' => virtual_machine_id
  }
  json = send_async_request(params)
  json['portforwardingrule']
end

#create_server(host_name, service_name, template_name, disk_name = nil, zone_name = nil, network_names = [], extra_params) ⇒ Object

Deploys a new server using the specified parameters.



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/knife-cloudstack/connection.rb', line 173

def create_server(host_name, service_name, template_name, disk_name=nil, zone_name=nil, network_names=[], extra_params)

  if host_name then
    if get_server(host_name) then
      puts "\nError: Server '#{host_name}' already exists."
      exit 1
    end
  end

  service = get_service_offering(service_name)
  if !service then
    puts "\nError: Service offering '#{service_name}' is invalid"
    exit 1
  end

  template = get_template(template_name, zone_name)
  template = get_iso(template_name, zone_name) unless template

  if !template then
    puts "\nError: Template / ISO name: '#{template_name}' is invalid"
    exit 1
  end

  if disk_name then
    disk = get_disk_offering(disk_name)
    if !disk then
      puts "\nError: Disk offering '#{disk_name}' is invalid"
      exit 1
    end
  end

  zone = zone_name ? get_zone(zone_name) : get_default_zone
  if !zone then
    msg = zone_name ? "Zone '#{zone_name}' is invalid" : "No default zone found"
    puts "\nError: #{msg}"
    exit 1
  end

  if zone['networktype'] != 'Basic' then
  # If this is a Basic zone no networkids are needed in the params

    networks = []
    if network_names.nil? then
      networks << get_default_network(zone['id'])
    else
      network_names.each do |name|
        network = get_network(name)
        if !network then
          puts "\nError: Network '#{name}' not found"
        end
        networks << get_network(name)
      end
    end

    if networks.empty? then
      networks << get_default_network(zone['id'])
    end
    if networks.empty? then
      puts "\nError: No default network found"
      exit 1
    end
    network_ids = networks.map { |network|
      network['id']
    }

    params = {
        'command' => 'deployVirtualMachine',
        'serviceOfferingId' => service['id'],
        'templateId' => template['id'],
        'zoneId' => zone['id'],
        'networkids' => network_ids.join(',')
    }

  else

    params = {
        'command' => 'deployVirtualMachine',
        'serviceOfferingId' => service['id'],
        'templateId' => template['id'],
        'zoneId' => zone['id']
    }

  end

  params.merge!(extra_params) if extra_params

  params['name'] = host_name if host_name
  params['diskOfferingId'] = disk['id'] if disk

  json = send_async_request(params)
  json['virtualmachine']
end

#data_filter(data, filters) ⇒ Object

Filter data on regex or just on string



558
559
560
561
562
563
564
565
566
567
568
569
# File 'lib/knife-cloudstack/connection.rb', line 558

def data_filter(data, filters)
  filters.split(',').each do |filter|
    field = filter.split(':').first.strip.downcase
    search = filter.split(':').last.strip
    if search =~ /^\/.*\/?/
      data = data.find_all { |k| k["#{field}"].to_s =~ search.to_regexp } if field && search
    else
      data = data.find_all { |k| k["#{field}"].to_s == "#{search}" } if field && search
    end
  end
  data
end

#delete_server(name, expunge) ⇒ Object

Deletes the server with the specified name.



270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/knife-cloudstack/connection.rb', line 270

def delete_server(name, expunge)
  server = get_server(name)
  if !server || !server['id'] then
    puts "\nError: Virtual machine '#{name}' does not exist"
    exit 1
  end

  params = {
      'command' => 'destroyVirtualMachine',
      'id' => server['id'],
      'expunge' => expunge
  }

  json = send_async_request(params)
  json['virtualmachine']
end

#delete_volume(name) ⇒ Object

Deletes the volume with the specified name.



497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
# File 'lib/knife-cloudstack/connection.rb', line 497

def delete_volume(name)
  volume = get_volume(name)
  if !volume || !volume['id'] then
    puts "\nError: Volume '#{name}' does not exist"
    exit 1
  end

  params = {
      'command' => 'deleteVolume',
      'id' => volume['id']
  }

  json = send_request(params)
  json['success']
end

#disable_static_nat(ipaddress) ⇒ Object



759
760
761
762
763
764
765
# File 'lib/knife-cloudstack/connection.rb', line 759

def disable_static_nat(ipaddress)
  params = {
    'command' => 'disableStaticNat',
    'ipAddressId' => ipaddress['id']
  }
  send_async_request(params)
end

#disassociate_ip_address(id) ⇒ Object

Disassociates an ip address from the account.

Returns true if successful, false otherwise.



807
808
809
810
811
812
813
814
# File 'lib/knife-cloudstack/connection.rb', line 807

def disassociate_ip_address(id)
  params = {
      'command' => 'disassociateIpAddress',
      'id' => id
  }
  json = send_async_request(params)
  json['success']
end

#enable_static_nat(ipaddress_id, virtualmachine_id) ⇒ Object



750
751
752
753
754
755
756
757
# File 'lib/knife-cloudstack/connection.rb', line 750

def enable_static_nat(ipaddress_id, virtualmachine_id)
  params = {
    'command' => 'enableStaticNat',
    'ipAddressId' => ipaddress_id,
    'virtualmachineId' => virtualmachine_id
  }
  send_request(params)
end

#get_default_network(zone) ⇒ Object

Finds the default network.



597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
# File 'lib/knife-cloudstack/connection.rb', line 597

def get_default_network(zone)
  params = {
      'command' => 'listNetworks',
      'isDefault' => true,
      'zoneid' => zone
  }
  json = send_request(params)

  networks = json['network']
  return nil if !networks || networks.empty?

  default = networks.first
  return default if networks.length == 1

  networks.each { |n|
    if n['type'] == 'Direct' then
      default = n
      break
    end
  }

  default
end

#get_default_zoneObject

Finds the default zone for your account.



684
685
686
687
688
689
690
691
692
693
694
695
696
# File 'lib/knife-cloudstack/connection.rb', line 684

def get_default_zone
  params = {
      'command' => 'listZones',
      'available' => 'true'
  }
  json = send_request(params)

  zones = json['zone']
  return nil unless zones
  # zones.sort! # sort zones so we always return the same zone
  # !this gives error in our production environment so need to retest this
  zones.first
end

#get_disk_offering(name) ⇒ Object

Finds the disk offering with the specified name.



459
460
461
462
463
464
465
466
467
468
469
470
471
472
# File 'lib/knife-cloudstack/connection.rb', line 459

def get_disk_offering(name)
  params = {
      'command' => 'listDiskOfferings',
  }
  json = send_request(params)
  disks = json['diskoffering']

  return nil if !disks

  disks.each { |d|
    return d if d['name'] == name
  }
  nil
end

#get_iso(name, zone_name = nil) ⇒ Object

Finds the iso with the specified name.



431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
# File 'lib/knife-cloudstack/connection.rb', line 431

def get_iso(name, zone_name=nil)
  zone = zone_name ? get_zone(zone_name) : get_default_zone

  params = {
      'command' => 'listIsos',
      'isoFilter' => 'executable',
  }
  params['zoneid'] = zone['id'] if zone

  json = send_request(params)
  iso = json['iso']
  return nil unless iso

  iso.each { |i|
    if name.is_uuid? then
      return i if i['id'] == name
    else
      return i if i['name'] == name
    end
  }
  nil
end

#get_network(name) ⇒ Object

Finds the network with the specified name.



575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
# File 'lib/knife-cloudstack/connection.rb', line 575

def get_network(name)
  params = {
      'command' => 'listNetworks'
  }
  json = send_request(params)

  networks = json['network']
  return nil unless networks

  networks.each { |n|
    if name.is_uuid? then
      return n if n['id'] == name
    else
      return n if n['name'] == name
    end
  }
  nil
end

#get_project(name) ⇒ Object

Fetch project with the specified name



535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
# File 'lib/knife-cloudstack/connection.rb', line 535

def get_project(name)
  params = {
    'command' => 'listProjects',
	'listall' => true
  }

  json = send_request(params)
  projects = json['project']
  return nil unless projects

  projects.each { |n|
    if name.is_uuid? then
      return n if n['id'] == name
    else
      return n if n['name'] == name
    end
  }
  nil
end

#get_project_id(name) ⇒ Object

Get project id



67
68
69
70
71
72
73
74
# File 'lib/knife-cloudstack/connection.rb', line 67

def get_project_id(name)
  project = get_project(name)
  if !project then
    puts "Project #{project_name} does not exist"
    exit 1
  end
  project['id']
end

#get_public_ip_address(ip_address) ⇒ Object

Finds the public ip address for a given ip address string.



713
714
715
716
717
718
719
720
721
# File 'lib/knife-cloudstack/connection.rb', line 713

def get_public_ip_address(ip_address)
  params = {
      'command' => 'listPublicIpAddresses',
      'ipaddress' => ip_address
  }
  json = send_request(params)
  return nil unless json['publicipaddress']
  json['publicipaddress'].first
end

#get_server(name) ⇒ Object

Finds the server with the specified name.



79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/knife-cloudstack/connection.rb', line 79

def get_server(name)
  params = {
      'command' => 'listVirtualMachines',
      'name' => name
  }
  json = send_request(params)
  machines = json['virtualmachine']

  if !machines || machines.empty? then
    return nil
  end
  machine = machines.select { |item| name == item['name'] }
  machine.first
end

#get_server_default_nic(server) ⇒ Object



141
142
143
144
145
# File 'lib/knife-cloudstack/connection.rb', line 141

def get_server_default_nic(server)
  server['nic'].each do |nic|
    return nic if nic['isdefault']
  end
end

#get_server_fqdn(server) ⇒ Object

Returns the fully qualified domain name for a server.



126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/knife-cloudstack/connection.rb', line 126

def get_server_fqdn(server)
  return nil unless server

  nic = get_server_default_nic(server) || {}
  networks = list_networks || {}

  id = nic['networkid']
  network = networks.select { |net|
    net['id'] == id
  }.first
  return nil unless network

  "#{server['name']}.#{network['networkdomain']}"
end

#get_server_public_ip(server, cached_rules = nil, cached_nat = nil) ⇒ Object

Finds the public ip for a server



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/knife-cloudstack/connection.rb', line 97

def get_server_public_ip(server, cached_rules=nil, cached_nat=nil)
  return nil unless server
  # find the public ip
  nic = get_server_default_nic(server)

  ssh_rule = get_ssh_port_forwarding_rule(server, cached_rules)
  return ssh_rule['ipaddress'] if ssh_rule

  winrm_rule = get_winrm_port_forwarding_rule(server, cached_rules)
  return winrm_rule['ipaddress'] if winrm_rule

  #check for static NAT
  if cached_nat
    ip_addr = cached_nat.find {|v| v['virtualmachineid'] == server['id']}
  else
    ip_addr = list_public_ip_addresses.find {|v| v['virtualmachineid'] == server['id']}
  end
  if ip_addr
    return ip_addr['ipaddress']
  end
  if nic.empty?
    return []
  end
  nic['ipaddress'] || []
end

#get_service_offering(name) ⇒ Object

Finds the service offering with the specified name.



351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
# File 'lib/knife-cloudstack/connection.rb', line 351

def get_service_offering(name)

  # TODO: use name parameter
  # listServiceOfferings in CloudStack 2.2 doesn't seem to work
  # when the name parameter is specified. When this is fixed,
  # the name parameter should be added to the request.
  params = {
      'command' => 'listServiceOfferings'
  }
  json = send_request(params)

  services = json['serviceoffering']
  return nil unless services

  services.each { |s|
    if name.is_uuid? then
      return s if s['id'] == name
    else
      return s if s['name'] == name
    end
  }
  nil
end

#get_ssh_port_forwarding_rule(server, cached_rules = nil) ⇒ Object

Gets the SSH port forwarding rule for the specified server.



830
831
832
833
834
835
836
837
# File 'lib/knife-cloudstack/connection.rb', line 830

def get_ssh_port_forwarding_rule(server, cached_rules=nil)
  rules = cached_rules || list_port_forwarding_rules || []
  rules.find_all { |r|
    r['virtualmachineid'] == server['id'] &&
        r['privateport'] == '22'&&
        r['publicport'] == '22'
  }.first
end

#get_template(name, zone_name = nil) ⇒ Object

Finds the template with the specified name.



398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
# File 'lib/knife-cloudstack/connection.rb', line 398

def get_template(name, zone_name=nil)

  # TODO: use name parameter
  # listTemplates in CloudStack 2.2 doesn't seem to work
  # when the name parameter is specified. When this is fixed,
  # the name parameter should be added to the request.

  zone = zone_name ? get_zone(zone_name) : get_default_zone

  params = {
      'command' => 'listTemplates',
      'templateFilter' => 'executable',
  }
  params['zoneid'] = zone['id'] if zone

  json = send_request(params)

  templates = json['template']
  return nil unless templates

  templates.each { |t|
    if name.is_uuid? then
      return t if t['id'] == name
    else
      return t if t['name'] == name
    end
  }
  nil
end

#get_volume(name) ⇒ Object

Finds the volume with the specified name.



478
479
480
481
482
483
484
485
486
487
488
489
490
491
# File 'lib/knife-cloudstack/connection.rb', line 478

def get_volume(name)
  params = {
      'command' => 'listVolumes',
      'name' => name
  }
  json = send_request(params)
  volumes = json['volume']

  if !volumes || volumes.empty? then
    return nil
  end
  volume = volumes.select { |item| name == item['name'] }
  volume.first
end

#get_winrm_port_forwarding_rule(server, cached_rules = nil) ⇒ Object

Gets the WINRM port forwarding rule for the specified server.



842
843
844
845
846
847
848
849
850
851
# File 'lib/knife-cloudstack/connection.rb', line 842

def get_winrm_port_forwarding_rule(server, cached_rules=nil)
  rules = cached_rules || list_port_forwarding_rules || []
  rules.find_all { |r|
    r['virtualmachineid'] == server['id'] &&
       (r['privateport'] == '5985' &&
        r['publicport'] == '5985') ||
       (r['privateport'] == '5986' &&
        r['publicport'] == '5986')
  }.first
end

#get_zone(name) ⇒ Object

Finds the zone with the specified name.



635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
# File 'lib/knife-cloudstack/connection.rb', line 635

def get_zone(name)
  params = {
      'command' => 'listZones',
      'available' => 'true'
  }
  json = send_request(params)

  networks = json['zone']
  return nil unless networks

  networks.each { |z|
    if name.is_uuid? then
      return z if z['id'] == name
    else
      return z if z['name'] == name
    end
  }
  nil
end

#http_client_builderObject



869
870
871
872
873
874
875
876
877
878
879
# File 'lib/knife-cloudstack/connection.rb', line 869

def http_client_builder
  http_proxy = proxy_uri
  if http_proxy.nil?
    Net::HTTP
  else
    Chef::Log.debug("Using #{http_proxy.host}:#{http_proxy.port} for proxy")
    user = http_proxy.user if http_proxy.user
    pass = http_proxy.password if http_proxy.password
    Net::HTTP.Proxy(http_proxy.host, http_proxy.port, user, pass)
  end
end

#list_networksObject

Lists all available networks.



624
625
626
627
628
629
630
# File 'lib/knife-cloudstack/connection.rb', line 624

def list_networks
  params = {
      'command' => 'listNetworks'
  }
  json = send_request(params)
  json['network'] || []
end

#list_object(params, json_result) ⇒ Object

List all the objects based on the command that is specified.



150
151
152
153
154
155
156
157
# File 'lib/knife-cloudstack/connection.rb', line 150

def list_object(params, json_result)
  json = send_request(params)
  Chef::Log.debug("JSON (list_object) result: #{json}")

  result = json["#{json_result}"] || []
  result = data_filter(result, params['filter']) if params['filter']
  result
end

#list_port_forwarding_rules(ip_address_id = nil, listall = false) ⇒ Object

Lists all port forwarding rules.



819
820
821
822
823
824
825
# File 'lib/knife-cloudstack/connection.rb', line 819

def list_port_forwarding_rules(ip_address_id=nil, listall=false)
  params = { 'command' => 'listPortForwardingRules' }
  params['ipAddressId'] = ip_address_id if ip_address_id
  params['listall'] = listall
  json = send_request(params)
  json['portforwardingrule']
end

#list_public_ip_addresses(listall = false) ⇒ Object



723
724
725
726
727
728
729
# File 'lib/knife-cloudstack/connection.rb', line 723

def list_public_ip_addresses(listall=false)
  params = { 'command' => 'listPublicIpAddresses' }
  params['listall'] = listall

  json = send_request(params)
  return json['publicipaddress'] || []
end

#list_security_groupsObject



386
387
388
389
390
391
392
# File 'lib/knife-cloudstack/connection.rb', line 386

def list_security_groups
  params = {
      'command' => 'listSecurityGroups'
  }
  json = send_request(params)
  json['securitygroups'] || []
end

#list_serversObject

Lists all the servers in your account.



162
163
164
165
166
167
168
# File 'lib/knife-cloudstack/connection.rb', line 162

def list_servers
  params = {
      'command' => 'listVirtualMachines'
  }
  json = send_request(params)
  json['virtualmachine'] || []
end

#list_service_offeringsObject

Lists all available service offerings.



378
379
380
381
382
383
384
# File 'lib/knife-cloudstack/connection.rb', line 378

def list_service_offerings
  params = {
      'command' => 'listServiceOfferings'
  }
  json = send_request(params)
  json['serviceoffering'] || []
end

#list_templates(filter) ⇒ Object

Lists all templates that match the specified filter.

Allowable filter values are:

  • featured - templates that are featured and are public

  • self - templates that have been registered/created by the owner

  • self-executable - templates that have been registered/created by the owner that can be used to deploy a new VM

  • executable - all templates that can be used to deploy a new VM

  • community - templates that are public



524
525
526
527
528
529
530
531
532
# File 'lib/knife-cloudstack/connection.rb', line 524

def list_templates(filter)
  filter ||= 'featured'
  params = {
      'command' => 'listTemplates',
      'templateFilter' => filter
  }
  json = send_request(params)
  json['template'] || []
end

#list_zonesObject

Lists all available zones.



701
702
703
704
705
706
707
708
# File 'lib/knife-cloudstack/connection.rb', line 701

def list_zones
  params = {
      'command' => 'listZones',
      'available' => 'true'
  }
  json = send_request(params)
  json['zone'] || []
end

#proxy_uriObject



881
882
883
884
885
886
# File 'lib/knife-cloudstack/connection.rb', line 881

def proxy_uri
  return nil if @api_proxy.nil?
  result = URI.parse(@api_proxy)
  return result unless result.host.nil? || result.host.empty?
  nil
end

#reboot_server(name) ⇒ Object

Reboot the server with the specified name.



332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
# File 'lib/knife-cloudstack/connection.rb', line 332

def reboot_server(name)
  server = get_server(name)
  if !server || !server['id'] then
    puts "\nError: Virtual machine '#{name}' does not exist"
    exit 1
  end

  params = {
      'command' => 'rebootVirtualMachine',
      'id' => server['id']
  }

  json = send_async_request(params)
  json['virtualmachine']
end

#remove_nic_from_vm(nic_id, server_id) ⇒ Object



670
671
672
673
674
675
676
677
678
679
# File 'lib/knife-cloudstack/connection.rb', line 670

def remove_nic_from_vm(nic_id, server_id)
  params = {
    'command' => 'removeNicFromVirtualMachine',
    'nicid' => nic_id,
    'virtualmachineid' => server_id,
  }

  json = send_async_request(params)
  json['virtualmachine']
end

#send_async_request(params) ⇒ Object

Sends an asynchronous request and waits for the response.

The contents of the ‘jobresult’ element are returned upon completion of the command.



955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
# File 'lib/knife-cloudstack/connection.rb', line 955

def send_async_request(params)

  json = send_request(params)

  params = {
      'command' => 'queryAsyncJobResult',
      'jobId' => json['jobid']
  }

  max_tries = (ASYNC_TIMEOUT / ASYNC_POLL_INTERVAL).round
  max_tries.times do
    json = send_request(params)
    status = json['jobstatus']

    print "."

    if status == 1 then
      print "\n"
      return json['jobresult']
    elsif status == 2 then
      print "\n"
      puts "Request failed (#{json['jobresultcode']}): #{json['jobresult']}"
      exit 1
    end

    STDOUT.flush
    sleep ASYNC_POLL_INTERVAL
  end

  print "\n"
  puts "Error: Asynchronous request timed out"
  exit 1
end

#send_request(params) ⇒ Object

Sends a synchronous request to the CloudStack API and returns the response as a Hash.

The wrapper element of the response (e.g. mycommandresponse) is discarded and the contents of that element are returned.



894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
# File 'lib/knife-cloudstack/connection.rb', line 894

def send_request(params)
  if @project_id
    params['projectId'] = @project_id
  end
  params['response'] = 'json'
  params['apiKey'] = @api_key

  params_arr = []
  params.sort.each { |elem|
    params_arr << elem[0].to_s + '=' + CGI.escape(elem[1].to_s).gsub('+', '%20').gsub(' ','%20')
  }
  data = params_arr.join('&')
  signature = OpenSSL::HMAC.digest('sha1', @secret_key, data.downcase)
  signature = Base64.encode64(signature).chomp
  signature = CGI.escape(signature)

  if @api_url.nil? || @api_url.empty?
    puts "Error: Please specify a valid API URL."
    exit 1
  end

  url = "#{@api_url}?#{data}&signature=#{signature}"
  Chef::Log.debug("URL: #{url}")
  uri = URI.parse(url)

  http = http_client_builder.new(uri.host, uri.port)

  if uri.scheme == "https"
    http.use_ssl = true
    # Still need to do some testing on SSL, so will fix this later
    if @no_ssl_verify
      http.verify_mode = OpenSSL::SSL::VERIFY_NONE
    else
      http.verify_mode = OpenSSL::SSL::VERIFY_NONE
    end
  end
  request = Net::HTTP::Get.new(uri.request_uri)
  response = http.request(request)

  if !response.is_a?(Net::HTTPOK) then
    case response.code
    when "432"
      puts "\n"
      puts "Error #{response.code}: Your account does not have the right to execute this command is locked or the command does not exist."
    else
      puts "Error #{response.code}: #{response.message}"
      puts JSON.pretty_generate(JSON.parse(response.body))
      puts "URL: #{url}"
    end
    exit 1
  end

  json = JSON.parse(response.body)
  json[params['command'].downcase + 'response']
end

#start_server(name) ⇒ Object

Start the server with the specified name.



312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'lib/knife-cloudstack/connection.rb', line 312

def start_server(name)
  server = get_server(name)
  if !server || !server['id'] then
    puts "\nError: Virtual machine '#{name}' does not exist"
    exit 1
  end

  params = {
      'command' => 'startVirtualMachine',
      'id' => server['id']
  }

  json = send_async_request(params)
  json['virtualmachine']
end

#stop_server(name, forced = nil) ⇒ Object

Stops the server with the specified name.



291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/knife-cloudstack/connection.rb', line 291

def stop_server(name, forced=nil)
  server = get_server(name)
  if !server || !server['id'] then
    puts "\nError: Virtual machine '#{name}' does not exist"
    exit 1
  end

  params = {
      'command' => 'stopVirtualMachine',
      'id' => server['id']
  }
  params['forced'] = true if forced

  json = send_async_request(params)
  json['virtualmachine']
end