vagrant-vcloud 0.4.4 → 0.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|