vagrant-vcloud 0.4.4 → 0.4.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +100 -38
- data/Rakefile +0 -4
- data/lib/vagrant-vcloud/action.rb +33 -9
- data/lib/vagrant-vcloud/action/build_vapp.rb +163 -56
- data/lib/vagrant-vcloud/action/forward_ports.rb +38 -28
- data/lib/vagrant-vcloud/action/handle_nat_port_collisions.rb +28 -2
- data/lib/vagrant-vcloud/action/inventory_check.rb +20 -14
- data/lib/vagrant-vcloud/action/power_off_vapp.rb +3 -1
- data/lib/vagrant-vcloud/action/power_on.rb +36 -9
- data/lib/vagrant-vcloud/action/read_ssh_info.rb +15 -1
- data/lib/vagrant-vcloud/action/shut_down.rb +33 -0
- data/lib/vagrant-vcloud/config.rb +173 -1
- data/lib/vagrant-vcloud/driver/base.rb +0 -0
- data/lib/vagrant-vcloud/driver/meta.rb +0 -0
- data/lib/vagrant-vcloud/driver/version_5_1.rb +480 -148
- data/lib/vagrant-vcloud/errors.rb +6 -0
- data/lib/vagrant-vcloud/model/forwarded_port.rb +28 -4
- data/lib/vagrant-vcloud/util/compile_forwarded_ports.rb +44 -3
- data/lib/vagrant-vcloud/version.rb +1 -1
- data/locales/en.yml +14 -1
- metadata +4 -3
File without changes
|
File without changes
|
@@ -37,7 +37,7 @@ module VagrantPlugins
|
|
37
37
|
@username = username
|
38
38
|
@password = password
|
39
39
|
@org_name = org_name
|
40
|
-
@api_version = '5.
|
40
|
+
@api_version = '5.5'
|
41
41
|
@id = nil
|
42
42
|
|
43
43
|
@cached_vapp_edge_public_ips = {}
|
@@ -571,7 +571,7 @@ module VagrantPlugins
|
|
571
571
|
end
|
572
572
|
|
573
573
|
##
|
574
|
-
#
|
574
|
+
# Poweroff a given VM
|
575
575
|
# Using undeploy as a REAL powerOff
|
576
576
|
# Only poweroff will put the VM into a partially powered off state.
|
577
577
|
def poweroff_vm(vm_id)
|
@@ -595,6 +595,31 @@ module VagrantPlugins
|
|
595
595
|
task_id
|
596
596
|
end
|
597
597
|
|
598
|
+
##
|
599
|
+
# Shutdown a given VM
|
600
|
+
# Using undeploy with shutdown, without VMware Tools this WILL FAIL.
|
601
|
+
#
|
602
|
+
def shutdown_vm(vm_id)
|
603
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
604
|
+
xml.UndeployVAppParams(
|
605
|
+
'xmlns' => 'http://www.vmware.com/vcloud/v1.5'
|
606
|
+
) { xml.UndeployPowerAction 'shutdown' }
|
607
|
+
end
|
608
|
+
|
609
|
+
params = {
|
610
|
+
'method' => :post,
|
611
|
+
'command' => "/vApp/vm-#{vm_id}/action/undeploy"
|
612
|
+
}
|
613
|
+
|
614
|
+
_response, headers = send_request(
|
615
|
+
params,
|
616
|
+
builder.to_xml,
|
617
|
+
'application/vnd.vmware.vcloud.undeployVAppParams+xml'
|
618
|
+
)
|
619
|
+
task_id = URI(headers['Location']).path.gsub('/api/task/', '')
|
620
|
+
task_id
|
621
|
+
end
|
622
|
+
|
598
623
|
##
|
599
624
|
# Suspend a given VM
|
600
625
|
def suspend_vm(vm_id)
|
@@ -688,7 +713,7 @@ module VagrantPlugins
|
|
688
713
|
).first[:href]).path.gsub('/api/task/', '')
|
689
714
|
|
690
715
|
catalog_id = URI(response.css(
|
691
|
-
"AdminCatalog Link
|
716
|
+
"AdminCatalog Link[type='application/vnd.vmware.vcloud.catalog+xml']"
|
692
717
|
).first[:href]).path.gsub('/api/catalog/', '')
|
693
718
|
|
694
719
|
{ :task_id => task_id, :catalog_id => catalog_id }
|
@@ -748,74 +773,120 @@ module VagrantPlugins
|
|
748
773
|
# - vapp_description: description of the target vapp
|
749
774
|
# - vm_list: hash with IDs of the VMs used in the composing process
|
750
775
|
# - network_config: hash of the network configuration for the vapp
|
751
|
-
def compose_vapp_from_vm(vdc, vapp_name, vapp_description, vm_list = {}, network_config =
|
776
|
+
def compose_vapp_from_vm(vdc, vapp_name, vapp_description, vm_list = {}, network_config = [], _cfg)
|
752
777
|
builder = Nokogiri::XML::Builder.new do |xml|
|
753
|
-
xml.ComposeVAppParams(
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
'powerOn' => 'false') {
|
778
|
+
xml.ComposeVAppParams('xmlns' => 'http://www.vmware.com/vcloud/v1.5',
|
779
|
+
'xmlns:ovf' => 'http://schemas.dmtf.org/ovf/envelope/1',
|
780
|
+
'deploy' => 'false',
|
781
|
+
'powerOn' => 'false',
|
782
|
+
'name' => vapp_name) {
|
759
783
|
xml.Description vapp_description
|
760
784
|
xml.InstantiationParams {
|
761
785
|
xml.NetworkConfigSection {
|
762
786
|
xml['ovf'].Info 'Configuration parameters for logical networks'
|
763
|
-
|
764
|
-
xml.
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
xml.
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
xml.
|
776
|
-
xml.
|
777
|
-
|
787
|
+
network_config.each do |network|
|
788
|
+
xml.NetworkConfig('networkName' => network[:name]) {
|
789
|
+
xml.Configuration {
|
790
|
+
if network[:fence_mode] != 'bridged'
|
791
|
+
xml.IpScopes {
|
792
|
+
xml.IpScope {
|
793
|
+
xml.IsInherited(network[:is_inherited] || 'false')
|
794
|
+
xml.Gateway network[:gateway]
|
795
|
+
xml.Netmask network[:netmask]
|
796
|
+
xml.Dns1 network[:dns1] if network[:dns1]
|
797
|
+
xml.Dns2 network[:dns2] if network[:dns2]
|
798
|
+
xml.DnsSuffix network[:dns_suffix] if network[:dns_suffix]
|
799
|
+
xml.IpRanges {
|
800
|
+
xml.IpRange {
|
801
|
+
xml.StartAddress network[:start_address]
|
802
|
+
xml.EndAddress network[:end_address]
|
803
|
+
}
|
778
804
|
}
|
779
805
|
}
|
780
806
|
}
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
807
|
+
end
|
808
|
+
xml.ParentNetwork("href" => "#{@api_url}/network/#{network[:parent_network]}") if network[:parent_network]
|
809
|
+
xml.FenceMode network[:fence_mode]
|
810
|
+
if network[:fence_mode] != 'bridged'
|
811
|
+
xml.Features {
|
812
|
+
if network[:dhcp_enabled] == 'true'
|
813
|
+
xml.DhcpService {
|
814
|
+
xml.IsEnabled "true"
|
815
|
+
xml.DefaultLeaseTime "3600"
|
816
|
+
xml.MaxLeaseTime "7200"
|
817
|
+
xml.IpRange {
|
818
|
+
xml.StartAddress network[:dhcp_start]
|
819
|
+
xml.EndAddress network[:dhcp_end]
|
820
|
+
}
|
821
|
+
}
|
822
|
+
end
|
823
|
+
xml.FirewallService {
|
824
|
+
xml.IsEnabled(network[:enable_firewall] || "false")
|
825
|
+
}
|
826
|
+
xml.NatService {
|
827
|
+
xml.IsEnabled "true"
|
828
|
+
xml.NatType "portForwarding"
|
829
|
+
xml.Policy(network[:nat_policy_type] || "allowTraffic")
|
830
|
+
}
|
794
831
|
}
|
795
|
-
|
796
|
-
|
832
|
+
end
|
833
|
+
}
|
797
834
|
}
|
798
|
-
|
835
|
+
end #networks
|
799
836
|
}
|
800
837
|
}
|
801
838
|
vm_list.each do |vm_name, vm_id|
|
802
839
|
xml.SourcedItem {
|
803
840
|
xml.Source('href' => "#{@api_url}/vAppTemplate/vm-#{vm_id}", 'name' => vm_name)
|
804
841
|
xml.InstantiationParams {
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
842
|
+
if _cfg.enable_guest_customization.nil? || _cfg.enable_guest_customization
|
843
|
+
xml.GuestCustomizationSection(
|
844
|
+
'xmlns' => 'http://www.vmware.com/vcloud/v1.5',
|
845
|
+
'xmlns:ovf' => 'http://schemas.dmtf.org/ovf/envelope/1') {
|
846
|
+
xml['ovf'].Info 'VM Guest Customization configuration'
|
847
|
+
xml.Enabled true
|
848
|
+
if _cfg.guest_customization_change_sid == true
|
849
|
+
xml.ChangeSid true
|
850
|
+
if _cfg.guest_customization_join_domain == true
|
851
|
+
xml.JoinDomainEnabled true
|
852
|
+
xml.DomainName _cfg.guest_customization_domain_name
|
853
|
+
xml.DomainUserName _cfg.guest_customization_domain_user_name
|
854
|
+
xml.DomainUserPassword _cfg.guest_customization_domain_user_password
|
855
|
+
xml.MachineObjectOU _cfg.guest_customization_domain_ou if !_cfg.guest_customization_domain_ou.nil?
|
856
|
+
end
|
857
|
+
end
|
858
|
+
if _cfg.guest_customization_admin_password_enabled
|
859
|
+
xml.AdminPasswordEnabled true
|
860
|
+
xml.AdminPasswordAuto true if _cfg.guest_customization_admin_password_auto
|
861
|
+
xml.AdminPassword _cfg.guest_customization_admin_password if !_cfg.guest_customization_admin_password.nil?
|
862
|
+
if _cfg.guest_customization_admin_auto_login == true
|
863
|
+
xml.AdminAutoLogonEnabled true
|
864
|
+
xml.AdminAutoLogonCount _cfg.guest_customization_admin_auto_login_count
|
865
|
+
end
|
866
|
+
else
|
867
|
+
xml.AdminPasswordEnabled false
|
868
|
+
end
|
869
|
+
xml.ResetPasswordRequired _cfg.guest_customization_admin_password_reset if !_cfg.guest_customization_admin_password_reset.nil?
|
870
|
+
xml.CustomizationScript{ xml.cdata(_cfg.guest_customization_script) } if !_cfg.guest_customization_script.nil?
|
871
|
+
xml.ComputerName vm_name
|
815
872
|
}
|
816
|
-
|
873
|
+
end
|
874
|
+
if _cfg.nics.nil? && network_config.length == 1
|
875
|
+
xml.NetworkConnectionSection(
|
876
|
+
'xmlns:ovf' => 'http://schemas.dmtf.org/ovf/envelope/1',
|
877
|
+
'type' => 'application/vnd.vmware.vcloud.networkConnectionSection+xml',
|
878
|
+
'href' => "#{@api_url}/vAppTemplate/vm-#{vm_id}/networkConnectionSection/") {
|
879
|
+
xml['ovf'].Info 'Network config for sourced item'
|
880
|
+
xml.PrimaryNetworkConnectionIndex '0'
|
881
|
+
xml.NetworkConnection('network' => network_config[0][:name]) {
|
882
|
+
xml.NetworkConnectionIndex '0'
|
883
|
+
xml.IsConnected 'true'
|
884
|
+
xml.IpAddressAllocationMode(network_config[0][:ip_allocation_mode] || 'POOL')
|
885
|
+
}
|
886
|
+
}
|
887
|
+
end
|
817
888
|
}
|
818
|
-
xml.NetworkAssignment('containerNetwork' => network_config[:name], 'innerNetwork' => network_config[:name])
|
889
|
+
xml.NetworkAssignment('containerNetwork' => network_config[0][:name], 'innerNetwork' => network_config[0][:name]) if _cfg.nics.nil? && network_config.length == 1
|
819
890
|
}
|
820
891
|
end
|
821
892
|
xml.AllEULAsAccepted 'true'
|
@@ -851,7 +922,7 @@ module VagrantPlugins
|
|
851
922
|
# - vm_list: hash with IDs of the VMs to be used in the composing process
|
852
923
|
# - network_config: hash of the network configuration for the vapp
|
853
924
|
|
854
|
-
def recompose_vapp_from_vm(vapp_id, vm_list = {}, network_config =
|
925
|
+
def recompose_vapp_from_vm(vapp_id, vm_list = {}, network_config = [], _cfg)
|
855
926
|
original_vapp = get_vapp(vapp_id)
|
856
927
|
|
857
928
|
builder = Nokogiri::XML::Builder.new do |xml|
|
@@ -862,23 +933,57 @@ module VagrantPlugins
|
|
862
933
|
xml.Description original_vapp[:description]
|
863
934
|
xml.InstantiationParams {}
|
864
935
|
vm_list.each do |vm_name, vm_id|
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
936
|
+
xml.SourcedItem {
|
937
|
+
xml.Source('href' => "#{@api_url}/vAppTemplate/vm-#{vm_id}", 'name' => vm_name)
|
938
|
+
xml.InstantiationParams {
|
939
|
+
if _cfg.enable_guest_customization.nil? || _cfg.enable_guest_customization
|
940
|
+
xml.GuestCustomizationSection(
|
941
|
+
'xmlns' => 'http://www.vmware.com/vcloud/v1.5',
|
942
|
+
'xmlns:ovf' => 'http://schemas.dmtf.org/ovf/envelope/1') {
|
943
|
+
xml['ovf'].Info 'VM Guest Customization configuration'
|
944
|
+
xml.Enabled true
|
945
|
+
if _cfg.guest_customization_change_sid == true
|
946
|
+
xml.ChangeSid true
|
947
|
+
if _cfg.guest_customization_join_domain == true
|
948
|
+
xml.JoinDomainEnabled true
|
949
|
+
xml.DomainName _cfg.guest_customization_domain_name
|
950
|
+
xml.DomainUserName _cfg.guest_customization_domain_user_name
|
951
|
+
xml.DomainUserPassword _cfg.guest_customization_domain_user_password
|
952
|
+
xml.MachineObjectOU _cfg.guest_customization_domain_ou if !_cfg.guest_customization_domain_ou.nil?
|
953
|
+
end
|
954
|
+
end
|
955
|
+
if _cfg.guest_customization_admin_password_enabled
|
956
|
+
xml.AdminPasswordEnabled true
|
957
|
+
xml.AdminPasswordAuto true if _cfg.guest_customization_admin_password_auto
|
958
|
+
xml.AdminPassword _cfg.guest_customization_admin_password if !_cfg.guest_customization_admin_password.nil?
|
959
|
+
if _cfg.guest_customization_admin_auto_login == true
|
960
|
+
xml.AdminAutoLogonEnabled true
|
961
|
+
xml.AdminAutoLogonCount _cfg.guest_customization_admin_auto_login_count
|
962
|
+
end
|
963
|
+
else
|
964
|
+
xml.AdminPasswordEnabled false
|
965
|
+
end
|
966
|
+
xml.ResetPasswordRequired _cfg.guest_customization_admin_password_reset if !_cfg.guest_customization_admin_password_reset.nil?
|
967
|
+
xml.CustomizationScript{ xml.cdata(_cfg.guest_customization_script) } if !_cfg.guest_customization_script.nil?
|
968
|
+
xml.ComputerName vm_name
|
969
|
+
}
|
970
|
+
end
|
971
|
+
if _cfg.nics.nil? && network_config.length == 1
|
972
|
+
xml.NetworkConnectionSection(
|
973
|
+
'xmlns:ovf' => 'http://schemas.dmtf.org/ovf/envelope/1',
|
974
|
+
'type' => 'application/vnd.vmware.vcloud.networkConnectionSection+xml',
|
975
|
+
'href' => "#{@api_url}/vAppTemplate/vm-#{vm_id}/networkConnectionSection/") {
|
976
|
+
xml['ovf'].Info 'Network config for sourced item'
|
977
|
+
xml.PrimaryNetworkConnectionIndex '0'
|
978
|
+
xml.NetworkConnection('network' => network_config[0][:name]) {
|
979
|
+
xml.NetworkConnectionIndex '0'
|
980
|
+
xml.IsConnected 'true'
|
981
|
+
xml.IpAddressAllocationMode(network_config[0][:ip_allocation_mode] || 'POOL')
|
982
|
+
}
|
983
|
+
}
|
984
|
+
end
|
879
985
|
}
|
880
|
-
|
881
|
-
xml.NetworkAssignment('containerNetwork' => network_config[:name], 'innerNetwork' => network_config[:name])
|
986
|
+
xml.NetworkAssignment('containerNetwork' => network_config[0][:name], 'innerNetwork' => network_config[0][:name]) if _cfg.nics.nil? && network_config.length == 1
|
882
987
|
}
|
883
988
|
end
|
884
989
|
xml.AllEULAsAccepted 'true'
|
@@ -1011,42 +1116,27 @@ module VagrantPlugins
|
|
1011
1116
|
# :vm_scoped_local_id => value[:vapp_scoped_local_id]
|
1012
1117
|
# }
|
1013
1118
|
|
1014
|
-
def add_vapp_port_forwarding_rules(vapp_id, network_name, config = {})
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
xml.NatRule {
|
1036
|
-
xml.VmRule {
|
1037
|
-
xml.ExternalPort nat_rule[:nat_external_port]
|
1038
|
-
xml.VAppScopedVmId nat_rule[:vapp_scoped_local_id]
|
1039
|
-
xml.VmNicId(nat_rule[:nat_vmnic_id] || '0')
|
1040
|
-
xml.InternalPort nat_rule[:nat_internal_port]
|
1041
|
-
xml.Protocol(nat_rule[:nat_protocol] || 'TCP')
|
1042
|
-
}
|
1043
|
-
}
|
1044
|
-
end
|
1045
|
-
}
|
1046
|
-
}
|
1047
|
-
}
|
1048
|
-
}
|
1049
|
-
}
|
1119
|
+
def add_vapp_port_forwarding_rules(vapp_id, network_name, edge_network_name, config = {})
|
1120
|
+
params = {
|
1121
|
+
'method' => :get,
|
1122
|
+
'command' => "/vApp/vapp-#{vapp_id}/networkConfigSection"
|
1123
|
+
}
|
1124
|
+
response, _headers = send_request(params)
|
1125
|
+
|
1126
|
+
nat_svc = response.css("/NetworkConfigSection/NetworkConfig[networkName='#{network_name}']/Configuration/Features/NatService").first
|
1127
|
+
|
1128
|
+
config[:nat_rules].each do |nr|
|
1129
|
+
nat_svc << (
|
1130
|
+
"<NatRule>" +
|
1131
|
+
"<VmRule>" +
|
1132
|
+
"<ExternalPort>#{nr[:nat_external_port]}</ExternalPort>" +
|
1133
|
+
"<VAppScopedVmId>#{nr[:vapp_scoped_local_id]}</VAppScopedVmId>" +
|
1134
|
+
"<VmNicId>#{nr[:nat_vmnic_id]}</VmNicId>" +
|
1135
|
+
"<InternalPort>#{nr[:nat_internal_port]}</InternalPort>" +
|
1136
|
+
"<Protocol>#{nr[:nat_protocol]}</Protocol>" +
|
1137
|
+
"</VmRule>" +
|
1138
|
+
"</NatRule>"
|
1139
|
+
)
|
1050
1140
|
end
|
1051
1141
|
|
1052
1142
|
params = {
|
@@ -1056,7 +1146,7 @@ module VagrantPlugins
|
|
1056
1146
|
|
1057
1147
|
_response, headers = send_request(
|
1058
1148
|
params,
|
1059
|
-
|
1149
|
+
response.to_xml,
|
1060
1150
|
'application/vnd.vmware.vcloud.networkConfigSection+xml'
|
1061
1151
|
)
|
1062
1152
|
|
@@ -1067,7 +1157,7 @@ module VagrantPlugins
|
|
1067
1157
|
# Get vApp port forwarding rules
|
1068
1158
|
#
|
1069
1159
|
# - vapp_id: id of the vApp
|
1070
|
-
def get_vapp_port_forwarding_rules(vapp_id)
|
1160
|
+
def get_vapp_port_forwarding_rules(vapp_id, network_name=nil)
|
1071
1161
|
params = {
|
1072
1162
|
'method' => :get,
|
1073
1163
|
'command' => "/vApp/vapp-#{vapp_id}/networkConfigSection"
|
@@ -1077,9 +1167,22 @@ module VagrantPlugins
|
|
1077
1167
|
|
1078
1168
|
# FIXME: this will return nil if the vApp uses multiple vApp Networks
|
1079
1169
|
# with Edge devices in natRouted/portForwarding mode.
|
1080
|
-
|
1081
|
-
'NetworkConfigSection/NetworkConfig
|
1170
|
+
nconfig = response.css(
|
1171
|
+
'NetworkConfigSection/NetworkConfig'
|
1082
1172
|
)
|
1173
|
+
config = nil
|
1174
|
+
if nconfig.size > 1
|
1175
|
+
nconfig.each {|c|
|
1176
|
+
pn = c.css('/Configuration/ParentNetwork')
|
1177
|
+
next if pn.size == 0
|
1178
|
+
if pn.first['name'] == network_name
|
1179
|
+
config = c.css('/Configuration')
|
1180
|
+
break
|
1181
|
+
end
|
1182
|
+
}
|
1183
|
+
else
|
1184
|
+
config = nconfig.css('/Configuration')
|
1185
|
+
end
|
1083
1186
|
fence_mode = config.css('/FenceMode').text
|
1084
1187
|
nat_type = config.css('/Features/NatService/NatType').text
|
1085
1188
|
|
@@ -1494,8 +1597,8 @@ module VagrantPlugins
|
|
1494
1597
|
# - NatType" is set to "portForwarding
|
1495
1598
|
# This will be required to know how to connect to VMs behind the Edge
|
1496
1599
|
# device.
|
1497
|
-
def get_vapp_edge_public_ip(vapp_id)
|
1498
|
-
return @cached_vapp_edge_public_ips[vapp_id] unless @cached_vapp_edge_public_ips[vapp_id].nil?
|
1600
|
+
def get_vapp_edge_public_ip(vapp_id, network_name=nil)
|
1601
|
+
return @cached_vapp_edge_public_ips["#{vapp_id}#{network_name}"] unless @cached_vapp_edge_public_ips["#{vapp_id}#{network_name}"].nil?
|
1499
1602
|
|
1500
1603
|
# Check the network configuration section
|
1501
1604
|
params = {
|
@@ -1507,9 +1610,22 @@ module VagrantPlugins
|
|
1507
1610
|
|
1508
1611
|
# FIXME: this will return nil if the vApp uses multiple vApp Networks
|
1509
1612
|
# with Edge devices in natRouted/portForwarding mode.
|
1510
|
-
|
1511
|
-
'NetworkConfigSection/NetworkConfig
|
1613
|
+
nconfig = response.css(
|
1614
|
+
'NetworkConfigSection/NetworkConfig'
|
1512
1615
|
)
|
1616
|
+
config = nil
|
1617
|
+
if nconfig.size > 1
|
1618
|
+
nconfig.each {|c|
|
1619
|
+
pn = c.css('/Configuration/ParentNetwork')
|
1620
|
+
next if pn.size == 0
|
1621
|
+
if pn.first['name'] == network_name
|
1622
|
+
config = c.css('/Configuration')
|
1623
|
+
break
|
1624
|
+
end
|
1625
|
+
}
|
1626
|
+
else
|
1627
|
+
config = nconfig.css('/Configuration')
|
1628
|
+
end
|
1513
1629
|
|
1514
1630
|
fence_mode = config.css('/FenceMode').text
|
1515
1631
|
nat_type = config.css('/Features/NatService/NatType').text
|
@@ -1530,7 +1646,7 @@ module VagrantPlugins
|
|
1530
1646
|
if edge_ip == ''
|
1531
1647
|
return nil
|
1532
1648
|
else
|
1533
|
-
@cached_vapp_edge_public_ips[vapp_id] = edge_ip
|
1649
|
+
@cached_vapp_edge_public_ips["#{vapp_id}#{network_name}"] = edge_ip
|
1534
1650
|
return edge_ip
|
1535
1651
|
end
|
1536
1652
|
end
|
@@ -1582,7 +1698,7 @@ module VagrantPlugins
|
|
1582
1698
|
|
1583
1699
|
@logger.debug("Getting vAppTemplate ID: #{vapp_template}")
|
1584
1700
|
descriptor_upload = URI(response.css(
|
1585
|
-
"Files Link
|
1701
|
+
"Files Link[rel='upload:default']"
|
1586
1702
|
).first[:href]).path.gsub('/transfer/', '')
|
1587
1703
|
transfer_guid = descriptor_upload.gsub('/descriptor.ovf', '')
|
1588
1704
|
|
@@ -1623,7 +1739,7 @@ module VagrantPlugins
|
|
1623
1739
|
while true
|
1624
1740
|
response, _headers = send_request(params)
|
1625
1741
|
@logger.debug('Request...')
|
1626
|
-
break unless response.css("Files Link
|
1742
|
+
break unless response.css("Files Link[rel='upload:default']").count == 1
|
1627
1743
|
sleep 1
|
1628
1744
|
end
|
1629
1745
|
|
@@ -1645,7 +1761,7 @@ module VagrantPlugins
|
|
1645
1761
|
}
|
1646
1762
|
response, _headers = send_request(params)
|
1647
1763
|
response.css(
|
1648
|
-
"Files File
|
1764
|
+
"Files File[bytesTransferred='0'] Link[rel='upload:default']"
|
1649
1765
|
).each do |file|
|
1650
1766
|
file_name = URI(file[:href]).path.gsub("/transfer/#{transfer_guid}/", '')
|
1651
1767
|
upload_filename = "#{ovf_dir}/#{file_name}"
|
@@ -1700,7 +1816,7 @@ module VagrantPlugins
|
|
1700
1816
|
|
1701
1817
|
# Cancel Task
|
1702
1818
|
cancel_hook = URI(response.css(
|
1703
|
-
"Tasks Task Link
|
1819
|
+
"Tasks Task Link[rel='task:cancel']"
|
1704
1820
|
).first[:href]).path.gsub('/api', '')
|
1705
1821
|
|
1706
1822
|
params = {
|
@@ -1838,6 +1954,41 @@ module VagrantPlugins
|
|
1838
1954
|
task_id
|
1839
1955
|
end
|
1840
1956
|
|
1957
|
+
##
|
1958
|
+
# Set VM Network Connection state
|
1959
|
+
def set_vm_network_connected(vm_id)
|
1960
|
+
params = {
|
1961
|
+
'method' => :get,
|
1962
|
+
'command' => "/vApp/vm-#{vm_id}/networkConnectionSection"
|
1963
|
+
}
|
1964
|
+
response, _headers = send_request(params)
|
1965
|
+
|
1966
|
+
changed = false
|
1967
|
+
response.css('NetworkConnection').each do |net|
|
1968
|
+
ic = net.css('IsConnected')
|
1969
|
+
if ic.text != 'true'
|
1970
|
+
ic.first.content = 'true'
|
1971
|
+
changed = true
|
1972
|
+
end
|
1973
|
+
end
|
1974
|
+
|
1975
|
+
if changed
|
1976
|
+
params = {
|
1977
|
+
'method' => :put,
|
1978
|
+
'command' => "/vApp/vm-#{vm_id}/networkConnectionSection"
|
1979
|
+
}
|
1980
|
+
|
1981
|
+
_response, headers = send_request(
|
1982
|
+
params,
|
1983
|
+
response.to_xml,
|
1984
|
+
'application/vnd.vmware.vcloud.networkConnectionSection+xml'
|
1985
|
+
)
|
1986
|
+
|
1987
|
+
task_id = URI(headers['Location']).path.gsub('/api/task/', '')
|
1988
|
+
end
|
1989
|
+
task_id
|
1990
|
+
end
|
1991
|
+
|
1841
1992
|
##
|
1842
1993
|
# Set VM Guest Customization Config
|
1843
1994
|
def set_vm_guest_customization(vm_id, computer_name, config = {})
|
@@ -1869,6 +2020,13 @@ module VagrantPlugins
|
|
1869
2020
|
|
1870
2021
|
# Enable VM Nested Hardware-Assisted Virtualization
|
1871
2022
|
def set_vm_nested_hypervisor(vm_id, enable)
|
2023
|
+
vm = get_vm(vm_id)
|
2024
|
+
if enable && vm[:hypervisor_enabled] == 'true'
|
2025
|
+
return nil
|
2026
|
+
elsif !enable && vm[:hypervisor_enabled] == 'false'
|
2027
|
+
return nil
|
2028
|
+
end
|
2029
|
+
|
1872
2030
|
action = enable ? "enable" : "disable"
|
1873
2031
|
params = {
|
1874
2032
|
'method' => :post,
|
@@ -1890,10 +2048,19 @@ module VagrantPlugins
|
|
1890
2048
|
}
|
1891
2049
|
|
1892
2050
|
changed = false
|
2051
|
+
instance_id = -1
|
2052
|
+
hdd_address_on_parent = -1
|
2053
|
+
hdd_parent_id = nil
|
2054
|
+
hdd_bus_type = nil
|
2055
|
+
hdd_bus_sub_type = nil
|
2056
|
+
hdd_count = 0
|
2057
|
+
nic_count = 0
|
2058
|
+
nic_address_on_parent = -1
|
1893
2059
|
response, _headers = send_request(params)
|
1894
2060
|
|
1895
2061
|
response.css('ovf|Item').each do |item|
|
1896
2062
|
type = item.css('rasd|ResourceType').first
|
2063
|
+
instance_id = [ instance_id, item.css('rasd|InstanceID').first.text.to_i ].max
|
1897
2064
|
if type.content == '3'
|
1898
2065
|
# cpus
|
1899
2066
|
if cfg.cpus
|
@@ -1912,7 +2079,127 @@ module VagrantPlugins
|
|
1912
2079
|
changed = true
|
1913
2080
|
end
|
1914
2081
|
end
|
1915
|
-
|
2082
|
+
elsif type.content == '10'
|
2083
|
+
# network card
|
2084
|
+
nic_address_on_parent = nic_address_on_parent + 1
|
2085
|
+
# nic_address_on_parent = [ nic_address_on_parent, item.css('rasd|AddressOnParent').first.text.to_i ].max
|
2086
|
+
next if !cfg.nics || nic_count == cfg.nics.length
|
2087
|
+
nic = cfg.nics[nic_count]
|
2088
|
+
|
2089
|
+
orig_mac = item.css('rasd|Address').first.text
|
2090
|
+
orig_ip = item.css('rasd|Connection').first['vcloud:ipAddress']
|
2091
|
+
orig_address_mode = item.css('rasd|Connection').first['vcloud:ipAddressingMode']
|
2092
|
+
orig_primary = item.css('rasd|Connection').first['vcloud:primaryNetworkConnection']
|
2093
|
+
orig_network = item.css('rasd|Connection').first.text
|
2094
|
+
orig_parent = item.css('rasd|AddressOnParent').first.text
|
2095
|
+
# resourceSubType cannot be changed for an existing network card
|
2096
|
+
|
2097
|
+
if !nic[:mac].nil?
|
2098
|
+
changed = true if nic[:mac].upcase != orig_mac.upcase
|
2099
|
+
end
|
2100
|
+
if !nic[:ip].nil?
|
2101
|
+
changed = true if orig_ip.nil? || nic[:ip].upcase != orig_ip.upcase
|
2102
|
+
end
|
2103
|
+
changed = true if nic[:ip_mode].upcase != orig_address_mode.upcase
|
2104
|
+
changed = true if nic[:primary] != orig_primary
|
2105
|
+
changed = true if nic[:network].upcase != orig_network.upcase
|
2106
|
+
changed = true if nic_address_on_parent != orig_parent
|
2107
|
+
|
2108
|
+
if changed
|
2109
|
+
item.css('rasd|Address').first.content = nic[:mac] if !nic[:mac].nil?
|
2110
|
+
item.css('rasd|AddressOnParent').first.content = nic_address_on_parent if nic_address_on_parent != orig_parent
|
2111
|
+
conn = item.css('rasd|Connection').first
|
2112
|
+
conn.content = nic[:network]
|
2113
|
+
if nic[:ip_mode].upcase == 'DHCP'
|
2114
|
+
conn['vcloud:ipAddressingMode'] = 'DHCP'
|
2115
|
+
elsif nic[:ip_mode].upcase == 'STATIC'
|
2116
|
+
conn['vcloud:ipAddressingMode'] = 'MANUAL'
|
2117
|
+
conn['vcloud:ipAddress'] = nic[:ip]
|
2118
|
+
elsif nic[:ip_mode].upcase == 'POOL'
|
2119
|
+
conn['vcloud:ipAddressingMode'] = 'POOL'
|
2120
|
+
conn['vcloud:ipAddress'] = nic[:ip] if !nic[:ip].nil?
|
2121
|
+
end
|
2122
|
+
conn['vcloud:primaryNetworkConnection'] = nic[:primary]
|
2123
|
+
end
|
2124
|
+
nic_count = nic_count + 1
|
2125
|
+
elsif type.content == '17'
|
2126
|
+
# hard disk
|
2127
|
+
hdd_count = hdd_count + 1
|
2128
|
+
if hdd_parent_id.nil?
|
2129
|
+
hdd_parent_id = item.css('rasd|Parent').first.text
|
2130
|
+
hdd_bus_type = item.css('rasd|HostResource').first[:busType]
|
2131
|
+
hdd_bus_sub_type = item.css('rasd|HostResource').first[:busSubType]
|
2132
|
+
end
|
2133
|
+
if hdd_parent_id == item.css('rasd|Parent').first.text
|
2134
|
+
hdd_address_on_parent = [ hdd_address_on_parent, item.css('rasd|AddressOnParent').first.text.to_i ].max
|
2135
|
+
end
|
2136
|
+
end
|
2137
|
+
end
|
2138
|
+
|
2139
|
+
if cfg.add_hdds
|
2140
|
+
changed = true
|
2141
|
+
cfg.add_hdds.each do |hdd_size|
|
2142
|
+
hdd_address_on_parent = hdd_address_on_parent + 1
|
2143
|
+
instance_id = instance_id + 1
|
2144
|
+
newhdd = Nokogiri::XML::Builder.new do |xml|
|
2145
|
+
xml.root('xmlns:rasd' => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData',
|
2146
|
+
'xmlns:ovf' => 'http://schemas.dmtf.org/ovf/envelope/1') do
|
2147
|
+
xml['ovf'].Item {
|
2148
|
+
xml['rasd'].AddressOnParent(hdd_address_on_parent)
|
2149
|
+
xml['rasd'].Description("Hard disk")
|
2150
|
+
xml['rasd'].ElementName("Hard disk #{hdd_address_on_parent+1}")
|
2151
|
+
xml['rasd'].HostResource()
|
2152
|
+
xml['rasd'].InstanceID(instance_id)
|
2153
|
+
xml['rasd'].Parent(hdd_parent_id)
|
2154
|
+
xml['rasd'].ResourceType(17)
|
2155
|
+
}
|
2156
|
+
end
|
2157
|
+
end
|
2158
|
+
hr = newhdd.doc.css('rasd|HostResource').first
|
2159
|
+
hr['xmlns:vcloud'] = 'http://www.vmware.com/vcloud/v1.5'
|
2160
|
+
hr['vcloud:busSubType'] = hdd_bus_sub_type
|
2161
|
+
hr['vcloud:busType'] = hdd_bus_type
|
2162
|
+
hr['vcloud:capacity'] = hdd_size
|
2163
|
+
response.css('ovf|Item').last.add_next_sibling(newhdd.doc.css('ovf|Item'))
|
2164
|
+
end
|
2165
|
+
end
|
2166
|
+
|
2167
|
+
if cfg.nics
|
2168
|
+
cfg.nics.each_with_index do |nic, i|
|
2169
|
+
next if i < nic_count
|
2170
|
+
changed = true
|
2171
|
+
nic_address_on_parent = nic_address_on_parent + 1
|
2172
|
+
instance_id = instance_id + 1
|
2173
|
+
newnic = Nokogiri::XML::Builder.new do |xml|
|
2174
|
+
xml.root('xmlns:rasd' => 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData',
|
2175
|
+
'xmlns:ovf' => 'http://schemas.dmtf.org/ovf/envelope/1') do
|
2176
|
+
xml['ovf'].Item {
|
2177
|
+
xml['rasd'].Address(nic[:mac]) if !nic[:mac].nil?
|
2178
|
+
xml['rasd'].AddressOnParent(nic_address_on_parent)
|
2179
|
+
xml['rasd'].AutomaticAllocation(true)
|
2180
|
+
xml['rasd'].Connection(nic[:network])
|
2181
|
+
xml['rasd'].Description("#{nic[:type] || :vmxnet3} ethernet adapter")
|
2182
|
+
xml['rasd'].ElementName("Network adapter #{nic_count}")
|
2183
|
+
xml['rasd'].InstanceID(instance_id)
|
2184
|
+
xml['rasd'].ResourceSubType(nic[:type] || :vmxnet3)
|
2185
|
+
xml['rasd'].ResourceType(10)
|
2186
|
+
}
|
2187
|
+
end
|
2188
|
+
end
|
2189
|
+
conn = newnic.doc.css('rasd|Connection').first
|
2190
|
+
conn['xmlns:vcloud'] = 'http://www.vmware.com/vcloud/v1.5'
|
2191
|
+
if nic[:ip_mode].upcase == 'DHCP'
|
2192
|
+
conn['vcloud:ipAddressingMode'] = 'DHCP'
|
2193
|
+
elsif nic[:ip_mode].upcase == 'STATIC'
|
2194
|
+
conn['vcloud:ipAddressingMode'] = 'MANUAL'
|
2195
|
+
conn['vcloud:ipAddress'] = nic[:ip]
|
2196
|
+
elsif nic[:ip_mode].upcase == 'POOL'
|
2197
|
+
conn['vcloud:ipAddressingMode'] = 'POOL'
|
2198
|
+
conn['vcloud:ipAddress'] = nic[:ip] if !nic[:ip].nil?
|
2199
|
+
end
|
2200
|
+
conn['vcloud:primaryNetworkConnection'] = nic[:primary]
|
2201
|
+
response.css('ovf|Item').last.add_next_sibling(newnic.doc.css('ovf|Item'))
|
2202
|
+
end
|
1916
2203
|
end
|
1917
2204
|
|
1918
2205
|
if changed
|
@@ -1935,6 +2222,63 @@ module VagrantPlugins
|
|
1935
2222
|
end
|
1936
2223
|
|
1937
2224
|
|
2225
|
+
##
|
2226
|
+
# Add metadata
|
2227
|
+
def set_vapp_metadata(id, data)
|
2228
|
+
task_id = set_metadata "vApp/vapp-#{id}", data
|
2229
|
+
task_id
|
2230
|
+
end
|
2231
|
+
|
2232
|
+
|
2233
|
+
##
|
2234
|
+
# Add metadata
|
2235
|
+
def set_vm_metadata(id, data)
|
2236
|
+
task_id = set_metadata "vApp/vm-#{id}", data
|
2237
|
+
task_id
|
2238
|
+
end
|
2239
|
+
|
2240
|
+
|
2241
|
+
##
|
2242
|
+
# Add metadata
|
2243
|
+
def set_metadata(link, data)
|
2244
|
+
params = {
|
2245
|
+
'method' => :post,
|
2246
|
+
'command' => "/#{link}/metadata"
|
2247
|
+
}
|
2248
|
+
|
2249
|
+
md = Nokogiri::XML::Builder.new do |xml|
|
2250
|
+
xml.Metadata('xmlns' => 'http://www.vmware.com/vcloud/v1.5',
|
2251
|
+
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
2252
|
+
'type' => 'application/vnd.vmware.vcloud.metadata+xml') do
|
2253
|
+
data.each do |d|
|
2254
|
+
xml.MetadataEntry('type' => 'application/vnd.vmware.vcloud.metadata.value+xml') {
|
2255
|
+
xml.Key(d[0])
|
2256
|
+
if d[1].kind_of?(Integer)
|
2257
|
+
typ = 'MetadataNumberValue'
|
2258
|
+
elsif !!d[1] == d[1] # boolean
|
2259
|
+
typ = 'MetadataBooleanValue'
|
2260
|
+
else
|
2261
|
+
typ = 'MetadataStringValue'
|
2262
|
+
end
|
2263
|
+
xml.TypedValue('xsi:type' => typ) {
|
2264
|
+
xml.Value(d[1])
|
2265
|
+
}
|
2266
|
+
}
|
2267
|
+
end
|
2268
|
+
end
|
2269
|
+
end
|
2270
|
+
|
2271
|
+
_response, headers = send_request(
|
2272
|
+
params,
|
2273
|
+
md.to_xml,
|
2274
|
+
'application/vnd.vmware.vcloud.metadata+xml'
|
2275
|
+
)
|
2276
|
+
|
2277
|
+
task_id = URI(headers['Location']).path.gsub('/api/task/', '')
|
2278
|
+
task_id
|
2279
|
+
|
2280
|
+
end
|
2281
|
+
|
1938
2282
|
##
|
1939
2283
|
# Fetch details about a given VM
|
1940
2284
|
def get_vm(vm_id)
|
@@ -1945,58 +2289,46 @@ module VagrantPlugins
|
|
1945
2289
|
|
1946
2290
|
response, _headers = send_request(params)
|
1947
2291
|
|
1948
|
-
|
1949
|
-
|
1950
|
-
).first.text
|
2292
|
+
hypervisor_enabled = response[:nestedHypervisorEnabled]
|
2293
|
+
os_desc = response.css('ovf|OperatingSystemSection ovf|Description').first.text
|
1951
2294
|
|
1952
2295
|
networks = {}
|
2296
|
+
primary_network = response.css('PrimaryNetworkConnectionIndex').first.text.to_i
|
1953
2297
|
response.css('NetworkConnection').each do |network|
|
1954
2298
|
ip = network.css('IpAddress').first
|
1955
2299
|
ip = ip.text if ip
|
2300
|
+
primary = false
|
2301
|
+
primary = true if network.css('NetworkConnectionIndex').first.text.to_i == primary_network
|
1956
2302
|
|
1957
2303
|
networks[network['network']] = {
|
1958
|
-
:
|
1959
|
-
|
1960
|
-
).first.text,
|
2304
|
+
:primary => primary,
|
2305
|
+
:index => network.css('NetworkConnectionIndex').first.text,
|
1961
2306
|
:ip => ip,
|
1962
|
-
:is_connected => network.css(
|
1963
|
-
|
1964
|
-
|
1965
|
-
:mac_address => network.css(
|
1966
|
-
'MACAddress'
|
1967
|
-
).first.text,
|
1968
|
-
:ip_allocation_mode => network.css(
|
1969
|
-
'IpAddressAllocationMode'
|
1970
|
-
).first.text
|
2307
|
+
:is_connected => network.css('IsConnected').first.text,
|
2308
|
+
:mac_address => network.css('MACAddress').first.text,
|
2309
|
+
:ip_allocation_mode => network.css('IpAddressAllocationMode').first.text
|
1971
2310
|
}
|
1972
2311
|
end
|
1973
2312
|
|
1974
|
-
admin_password = response.css(
|
1975
|
-
'GuestCustomizationSection AdminPassword'
|
1976
|
-
).first
|
2313
|
+
admin_password = response.css('GuestCustomizationSection AdminPassword').first
|
1977
2314
|
admin_password = admin_password.text if admin_password
|
1978
2315
|
|
1979
2316
|
# make the lines shorter by adjusting the nokogiri css namespace
|
1980
2317
|
guest_css = response.css('GuestCustomizationSection')
|
1981
2318
|
guest_customizations = {
|
1982
2319
|
:enabled => guest_css.css('Enabled').first.text,
|
1983
|
-
:admin_passwd_enabled => guest_css.css(
|
1984
|
-
|
1985
|
-
).first.text,
|
1986
|
-
:admin_passwd_auto => guest_css.css(
|
1987
|
-
'AdminPasswordAuto'
|
1988
|
-
).first.text,
|
2320
|
+
:admin_passwd_enabled => guest_css.css('AdminPasswordEnabled').first.text,
|
2321
|
+
:admin_passwd_auto => guest_css.css('AdminPasswordAuto').first.text,
|
1989
2322
|
:admin_passwd => admin_password,
|
1990
|
-
:reset_passwd_required => guest_css.css(
|
1991
|
-
'ResetPasswordRequired'
|
1992
|
-
).first.text,
|
2323
|
+
:reset_passwd_required => guest_css.css('ResetPasswordRequired').first.text,
|
1993
2324
|
:computer_name => guest_css.css('ComputerName').first.text
|
1994
2325
|
}
|
1995
2326
|
|
1996
2327
|
{
|
1997
2328
|
:os_desc => os_desc,
|
1998
2329
|
:networks => networks,
|
1999
|
-
:guest_customizations => guest_customizations
|
2330
|
+
:guest_customizations => guest_customizations,
|
2331
|
+
:hypervisor_enabled => hypervisor_enabled
|
2000
2332
|
}
|
2001
2333
|
end
|
2002
2334
|
end # Class Version 5.1
|