bosh_vcloud_cpi 0.4.9 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (276) hide show
  1. data/README.md +69 -0
  2. data/lib/cloud/vcloud/cache.rb +20 -0
  3. data/lib/cloud/vcloud/cloud.rb +253 -535
  4. data/lib/cloud/vcloud/errors.rb +9 -0
  5. data/lib/cloud/vcloud/file_uploader.rb +39 -0
  6. data/lib/cloud/vcloud/steps/add_catalog_item.rb +28 -0
  7. data/lib/cloud/vcloud/steps/add_networks.rb +40 -0
  8. data/lib/cloud/vcloud/steps/attach_detach_disk.rb +15 -0
  9. data/lib/cloud/vcloud/steps/create_disk.rb +29 -0
  10. data/lib/cloud/vcloud/steps/create_media.rb +41 -0
  11. data/lib/cloud/vcloud/steps/create_template.rb +27 -0
  12. data/lib/cloud/vcloud/steps/create_update_agent_env.rb +66 -0
  13. data/lib/cloud/vcloud/steps/delete.rb +12 -0
  14. data/lib/cloud/vcloud/steps/delete_catalog_media.rb +23 -0
  15. data/lib/cloud/vcloud/steps/delete_unused_networks.rb +20 -0
  16. data/lib/cloud/vcloud/steps/discard_suspended_state.rb +15 -0
  17. data/lib/cloud/vcloud/steps/eject_catalog_media.rb +29 -0
  18. data/lib/cloud/vcloud/steps/insert_catalog_media.rb +26 -0
  19. data/lib/cloud/vcloud/steps/instantiate.rb +59 -0
  20. data/lib/cloud/vcloud/steps/load_agent_env.rb +14 -0
  21. data/lib/cloud/vcloud/steps/poweroff.rb +21 -0
  22. data/lib/cloud/vcloud/steps/poweron.rb +17 -0
  23. data/lib/cloud/vcloud/steps/reboot.rb +13 -0
  24. data/lib/cloud/vcloud/steps/recompose.rb +19 -0
  25. data/lib/cloud/vcloud/steps/reconfigure_vm.rb +35 -0
  26. data/lib/cloud/vcloud/steps/save_agent_env.rb +43 -0
  27. data/lib/cloud/vcloud/steps/stemcell_info.rb +20 -0
  28. data/lib/cloud/vcloud/steps/undeploy.rb +19 -0
  29. data/lib/cloud/vcloud/steps/upload_media_files.rb +18 -0
  30. data/lib/cloud/vcloud/steps/upload_template_files.rb +29 -0
  31. data/lib/cloud/vcloud/steps.rb +100 -0
  32. data/lib/cloud/vcloud/vcd_client.rb +284 -0
  33. data/lib/cloud/vcloud/version.rb +1 -1
  34. data/lib/cloud/vcloud/xml/constants.rb +428 -0
  35. data/lib/cloud/vcloud/xml/wrapper.rb +292 -0
  36. data/lib/cloud/vcloud/xml/wrapper_classes/admin_catalog.rb +20 -0
  37. data/lib/cloud/vcloud/xml/wrapper_classes/admin_org.rb +15 -0
  38. data/lib/cloud/vcloud/xml/wrapper_classes/catalog.rb +20 -0
  39. data/lib/cloud/vcloud/xml/wrapper_classes/catalog_item.rb +27 -0
  40. data/lib/cloud/vcloud/xml/wrapper_classes/disk.rb +42 -0
  41. data/lib/cloud/vcloud/xml/wrapper_classes/disk_attach_or_detach_params.rb +12 -0
  42. data/lib/cloud/vcloud/xml/wrapper_classes/disk_create_params.rb +47 -0
  43. data/lib/cloud/vcloud/xml/wrapper_classes/entity.rb +11 -0
  44. data/lib/cloud/vcloud/xml/wrapper_classes/file.rb +11 -0
  45. data/lib/cloud/vcloud/xml/wrapper_classes/hard_disk_item_wrapper.rb +56 -0
  46. data/lib/cloud/vcloud/xml/wrapper_classes/instantiate_vapp_template_params.rb +71 -0
  47. data/lib/cloud/vcloud/xml/wrapper_classes/ip_scope.rb +55 -0
  48. data/lib/cloud/vcloud/xml/wrapper_classes/item.rb +32 -0
  49. data/lib/cloud/vcloud/xml/wrapper_classes/link_wrapper.rb +39 -0
  50. data/lib/cloud/vcloud/xml/wrapper_classes/media.rb +57 -0
  51. data/lib/cloud/vcloud/xml/wrapper_classes/media_insert_or_eject_params.rb +17 -0
  52. data/lib/cloud/vcloud/xml/wrapper_classes/metadata_value.rb +15 -0
  53. data/lib/cloud/vcloud/xml/wrapper_classes/network.rb +15 -0
  54. data/lib/cloud/vcloud/xml/wrapper_classes/network_config.rb +27 -0
  55. data/lib/cloud/vcloud/xml/wrapper_classes/network_config_section.rb +25 -0
  56. data/lib/cloud/vcloud/xml/wrapper_classes/network_connection.rb +71 -0
  57. data/lib/cloud/vcloud/xml/wrapper_classes/network_connection_section.rb +67 -0
  58. data/lib/cloud/vcloud/xml/wrapper_classes/nic_item_wrapper.rb +89 -0
  59. data/lib/cloud/vcloud/xml/wrapper_classes/org.rb +21 -0
  60. data/lib/cloud/vcloud/xml/wrapper_classes/org_network.rb +19 -0
  61. data/lib/cloud/vcloud/xml/wrapper_classes/org_vdc_network.rb +11 -0
  62. data/lib/cloud/vcloud/xml/wrapper_classes/recompose_vapp_wrapper.rb +51 -0
  63. data/lib/cloud/vcloud/xml/wrapper_classes/session.rb +24 -0
  64. data/lib/cloud/vcloud/xml/wrapper_classes/supported_versions.rb +19 -0
  65. data/lib/cloud/vcloud/xml/wrapper_classes/task.rb +32 -0
  66. data/lib/cloud/vcloud/xml/wrapper_classes/upload_vapp_template_params.rb +11 -0
  67. data/lib/cloud/vcloud/xml/wrapper_classes/vapp.rb +77 -0
  68. data/lib/cloud/vcloud/xml/wrapper_classes/vapp_template.rb +17 -0
  69. data/lib/cloud/vcloud/xml/wrapper_classes/vcloud.rb +15 -0
  70. data/lib/cloud/vcloud/xml/wrapper_classes/vdc.rb +59 -0
  71. data/lib/cloud/vcloud/xml/wrapper_classes/vdc_storage_profile.rb +15 -0
  72. data/lib/cloud/vcloud/xml/wrapper_classes/virtual_hardware_section.rb +68 -0
  73. data/lib/cloud/vcloud/xml/wrapper_classes/vm.rb +212 -0
  74. data/lib/cloud/vcloud/xml/xml_templates/AdminAllocatedExtIpRecord.xml +1 -0
  75. data/lib/cloud/vcloud/xml/xml_templates/AdminCatalog.xml +1 -0
  76. data/lib/cloud/vcloud/xml/xml_templates/AdminCatalogItemRecord.xml +1 -0
  77. data/lib/cloud/vcloud/xml/xml_templates/AdminCatalogRecord.xml +1 -0
  78. data/lib/cloud/vcloud/xml/xml_templates/AdminGroupRecord.xml +1 -0
  79. data/lib/cloud/vcloud/xml/xml_templates/AdminMediaRecord.xml +1 -0
  80. data/lib/cloud/vcloud/xml/xml_templates/AdminOrg.xml +1 -0
  81. data/lib/cloud/vcloud/xml/xml_templates/AdminOrgNetworkRecord.xml +1 -0
  82. data/lib/cloud/vcloud/xml/xml_templates/AdminShadowVmRecord.xml +1 -0
  83. data/lib/cloud/vcloud/xml/xml_templates/AdminTaskRecord.xml +1 -0
  84. data/lib/cloud/vcloud/xml/xml_templates/AdminUserRecord.xml +1 -0
  85. data/lib/cloud/vcloud/xml/xml_templates/AdminVAppNetworkRecord.xml +1 -0
  86. data/lib/cloud/vcloud/xml/xml_templates/AdminVAppRecord.xml +1 -0
  87. data/lib/cloud/vcloud/xml/xml_templates/AdminVAppReference.xml +1 -0
  88. data/lib/cloud/vcloud/xml/xml_templates/AdminVAppReferences.xml +1 -0
  89. data/lib/cloud/vcloud/xml/xml_templates/AdminVAppTemplateRecord.xml +1 -0
  90. data/lib/cloud/vcloud/xml/xml_templates/AdminVdc.xml +1 -0
  91. data/lib/cloud/vcloud/xml/xml_templates/AdminVdcRecord.xml +1 -0
  92. data/lib/cloud/vcloud/xml/xml_templates/AdminVdcReference.xml +1 -0
  93. data/lib/cloud/vcloud/xml/xml_templates/AdminVdcReferences.xml +1 -0
  94. data/lib/cloud/vcloud/xml/xml_templates/AdminVmRecord.xml +1 -0
  95. data/lib/cloud/vcloud/xml/xml_templates/AllEULAsAccepted.xml +1 -0
  96. data/lib/cloud/vcloud/xml/xml_templates/AllocatedExtIpRecord.xml +1 -0
  97. data/lib/cloud/vcloud/xml/xml_templates/BlockingTaskRecord.xml +1 -0
  98. data/lib/cloud/vcloud/xml/xml_templates/BlockingTaskReference.xml +1 -0
  99. data/lib/cloud/vcloud/xml/xml_templates/BlockingTaskReferences.xml +1 -0
  100. data/lib/cloud/vcloud/xml/xml_templates/CaptureVAppParams.xml +1 -0
  101. data/lib/cloud/vcloud/xml/xml_templates/Catalog.xml +1 -0
  102. data/lib/cloud/vcloud/xml/xml_templates/CatalogItem.xml +1 -0
  103. data/lib/cloud/vcloud/xml/xml_templates/CatalogItemRecord.xml +1 -0
  104. data/lib/cloud/vcloud/xml/xml_templates/CatalogItemReference.xml +1 -0
  105. data/lib/cloud/vcloud/xml/xml_templates/CatalogItemReferences.xml +1 -0
  106. data/lib/cloud/vcloud/xml/xml_templates/CatalogRecord.xml +1 -0
  107. data/lib/cloud/vcloud/xml/xml_templates/CatalogReference.xml +1 -0
  108. data/lib/cloud/vcloud/xml/xml_templates/CatalogReferences.xml +1 -0
  109. data/lib/cloud/vcloud/xml/xml_templates/CellRecord.xml +1 -0
  110. data/lib/cloud/vcloud/xml/xml_templates/CloneMediaParams.xml +1 -0
  111. data/lib/cloud/vcloud/xml/xml_templates/CloneVAppParams.xml +1 -0
  112. data/lib/cloud/vcloud/xml/xml_templates/CloneVAppTemplateParams.xml +1 -0
  113. data/lib/cloud/vcloud/xml/xml_templates/ComposeVAppParams.xml +17 -0
  114. data/lib/cloud/vcloud/xml/xml_templates/ControlAccessParams.xml +1 -0
  115. data/lib/cloud/vcloud/xml/xml_templates/CustomizationSection.xml +1 -0
  116. data/lib/cloud/vcloud/xml/xml_templates/DatastoreProviderVdcRelationRecord.xml +1 -0
  117. data/lib/cloud/vcloud/xml/xml_templates/DatastoreRecord.xml +1 -0
  118. data/lib/cloud/vcloud/xml/xml_templates/DatastoreReference.xml +1 -0
  119. data/lib/cloud/vcloud/xml/xml_templates/DatastoreReferences.xml +1 -0
  120. data/lib/cloud/vcloud/xml/xml_templates/DeployVAppParams.xml +1 -0
  121. data/lib/cloud/vcloud/xml/xml_templates/DhcpService.xml +1 -0
  122. data/lib/cloud/vcloud/xml/xml_templates/DiskAttachOrDetachParams.xml +5 -0
  123. data/lib/cloud/vcloud/xml/xml_templates/DiskCreateParams.xml +9 -0
  124. data/lib/cloud/vcloud/xml/xml_templates/DvSwitchRecord.xml +1 -0
  125. data/lib/cloud/vcloud/xml/xml_templates/Entity.xml +1 -0
  126. data/lib/cloud/vcloud/xml/xml_templates/Error.xml +1 -0
  127. data/lib/cloud/vcloud/xml/xml_templates/EventRecord.xml +1 -0
  128. data/lib/cloud/vcloud/xml/xml_templates/ExternalNetwork.xml +1 -0
  129. data/lib/cloud/vcloud/xml/xml_templates/File.xml +1 -0
  130. data/lib/cloud/vcloud/xml/xml_templates/FirewallService.xml +1 -0
  131. data/lib/cloud/vcloud/xml/xml_templates/GeneralOrgSettings.xml +1 -0
  132. data/lib/cloud/vcloud/xml/xml_templates/Group.xml +1 -0
  133. data/lib/cloud/vcloud/xml/xml_templates/GroupRecord.xml +1 -0
  134. data/lib/cloud/vcloud/xml/xml_templates/GroupReference.xml +1 -0
  135. data/lib/cloud/vcloud/xml/xml_templates/GroupReferences.xml +1 -0
  136. data/lib/cloud/vcloud/xml/xml_templates/GuestCustomizationSection.xml +1 -0
  137. data/lib/cloud/vcloud/xml/xml_templates/HostRecord.xml +1 -0
  138. data/lib/cloud/vcloud/xml/xml_templates/HostReference.xml +1 -0
  139. data/lib/cloud/vcloud/xml/xml_templates/HostReferences.xml +1 -0
  140. data/lib/cloud/vcloud/xml/xml_templates/InstantiateOvfParams.xml +1 -0
  141. data/lib/cloud/vcloud/xml/xml_templates/InstantiateVAppTemplateParams.xml +1 -0
  142. data/lib/cloud/vcloud/xml/xml_templates/IpScope.xml +12 -0
  143. data/lib/cloud/vcloud/xml/xml_templates/IpsecVpnLocalPeer.xml +1 -0
  144. data/lib/cloud/vcloud/xml/xml_templates/IpsecVpnPeer.xml +1 -0
  145. data/lib/cloud/vcloud/xml/xml_templates/IpsecVpnRemotePeer.xml +1 -0
  146. data/lib/cloud/vcloud/xml/xml_templates/IpsecVpnService.xml +1 -0
  147. data/lib/cloud/vcloud/xml/xml_templates/IpsecVpnThirdPartyPeer.xml +1 -0
  148. data/lib/cloud/vcloud/xml/xml_templates/Item.xml +3 -0
  149. data/lib/cloud/vcloud/xml/xml_templates/ItemVcd.xml +5 -0
  150. data/lib/cloud/vcloud/xml/xml_templates/LeaseSettingsSection.xml +1 -0
  151. data/lib/cloud/vcloud/xml/xml_templates/Link.xml +1 -0
  152. data/lib/cloud/vcloud/xml/xml_templates/Media.xml +5 -0
  153. data/lib/cloud/vcloud/xml/xml_templates/MediaInsertOrEjectParams.xml +4 -0
  154. data/lib/cloud/vcloud/xml/xml_templates/MediaRecord.xml +1 -0
  155. data/lib/cloud/vcloud/xml/xml_templates/MediaReference.xml +1 -0
  156. data/lib/cloud/vcloud/xml/xml_templates/MediaReferences.xml +1 -0
  157. data/lib/cloud/vcloud/xml/xml_templates/Metadata.xml +5 -0
  158. data/lib/cloud/vcloud/xml/xml_templates/MetadataEntry.xml +7 -0
  159. data/lib/cloud/vcloud/xml/xml_templates/MetadataValue.xml +8 -0
  160. data/lib/cloud/vcloud/xml/xml_templates/NatService.xml +1 -0
  161. data/lib/cloud/vcloud/xml/xml_templates/Network.xml +4 -0
  162. data/lib/cloud/vcloud/xml/xml_templates/NetworkAssignment.xml +1 -0
  163. data/lib/cloud/vcloud/xml/xml_templates/NetworkConfig.xml +21 -0
  164. data/lib/cloud/vcloud/xml/xml_templates/NetworkConfigSection.xml +1 -0
  165. data/lib/cloud/vcloud/xml/xml_templates/NetworkConnection.xml +11 -0
  166. data/lib/cloud/vcloud/xml/xml_templates/NetworkConnectionSection.xml +1 -0
  167. data/lib/cloud/vcloud/xml/xml_templates/NetworkPoolRecord.xml +1 -0
  168. data/lib/cloud/vcloud/xml/xml_templates/NetworkPoolReference.xml +1 -0
  169. data/lib/cloud/vcloud/xml/xml_templates/NetworkPoolReferences.xml +1 -0
  170. data/lib/cloud/vcloud/xml/xml_templates/NetworkRecord.xml +1 -0
  171. data/lib/cloud/vcloud/xml/xml_templates/NetworkReference.xml +1 -0
  172. data/lib/cloud/vcloud/xml/xml_templates/NetworkReferences.xml +1 -0
  173. data/lib/cloud/vcloud/xml/xml_templates/NetworkService.xml +1 -0
  174. data/lib/cloud/vcloud/xml/xml_templates/Org.xml +1 -0
  175. data/lib/cloud/vcloud/xml/xml_templates/OrgEmailSettings.xml +1 -0
  176. data/lib/cloud/vcloud/xml/xml_templates/OrgList.xml +1 -0
  177. data/lib/cloud/vcloud/xml/xml_templates/OrgNetwork.xml +1 -0
  178. data/lib/cloud/vcloud/xml/xml_templates/OrgNetworkRecord.xml +1 -0
  179. data/lib/cloud/vcloud/xml/xml_templates/OrgNetworkReference.xml +1 -0
  180. data/lib/cloud/vcloud/xml/xml_templates/OrgNetworkReferences.xml +1 -0
  181. data/lib/cloud/vcloud/xml/xml_templates/OrgPasswordPolicySettings.xml +1 -0
  182. data/lib/cloud/vcloud/xml/xml_templates/OrgRecord.xml +1 -0
  183. data/lib/cloud/vcloud/xml/xml_templates/OrgReference.xml +1 -0
  184. data/lib/cloud/vcloud/xml/xml_templates/OrgReferences.xml +1 -0
  185. data/lib/cloud/vcloud/xml/xml_templates/OrgSettings.xml +1 -0
  186. data/lib/cloud/vcloud/xml/xml_templates/OrgVAppTemplateLeaseSettings.xml +1 -0
  187. data/lib/cloud/vcloud/xml/xml_templates/OrgVdcNetwork.xml +1 -0
  188. data/lib/cloud/vcloud/xml/xml_templates/OrgVdcRecord.xml +1 -0
  189. data/lib/cloud/vcloud/xml/xml_templates/OrgVdcReference.xml +1 -0
  190. data/lib/cloud/vcloud/xml/xml_templates/OrgVdcReferences.xml +1 -0
  191. data/lib/cloud/vcloud/xml/xml_templates/OrgVdcResourcePoolRelationRecord.xml +1 -0
  192. data/lib/cloud/vcloud/xml/xml_templates/Owner.xml +1 -0
  193. data/lib/cloud/vcloud/xml/xml_templates/PortgroupRecord.xml +1 -0
  194. data/lib/cloud/vcloud/xml/xml_templates/ProductSectionList.xml +1 -0
  195. data/lib/cloud/vcloud/xml/xml_templates/ProviderVdc.xml +1 -0
  196. data/lib/cloud/vcloud/xml/xml_templates/ProviderVdcResourcePoolRelationRecord.xml +1 -0
  197. data/lib/cloud/vcloud/xml/xml_templates/PublishCatalogParams.xml +1 -0
  198. data/lib/cloud/vcloud/xml/xml_templates/QueryList.xml +1 -0
  199. data/lib/cloud/vcloud/xml/xml_templates/QueryResultRecords.xml +1 -0
  200. data/lib/cloud/vcloud/xml/xml_templates/RasdItemsList.xml +1 -0
  201. data/lib/cloud/vcloud/xml/xml_templates/RecomposeVAppParams.xml +17 -0
  202. data/lib/cloud/vcloud/xml/xml_templates/Record.xml +1 -0
  203. data/lib/cloud/vcloud/xml/xml_templates/Reference.xml +1 -0
  204. data/lib/cloud/vcloud/xml/xml_templates/References.xml +1 -0
  205. data/lib/cloud/vcloud/xml/xml_templates/RelocateParams.xml +1 -0
  206. data/lib/cloud/vcloud/xml/xml_templates/ResourceEntity.xml +1 -0
  207. data/lib/cloud/vcloud/xml/xml_templates/ResourcePoolRecord.xml +1 -0
  208. data/lib/cloud/vcloud/xml/xml_templates/Right.xml +1 -0
  209. data/lib/cloud/vcloud/xml/xml_templates/RightRecord.xml +1 -0
  210. data/lib/cloud/vcloud/xml/xml_templates/RightReference.xml +1 -0
  211. data/lib/cloud/vcloud/xml/xml_templates/RightReferences.xml +1 -0
  212. data/lib/cloud/vcloud/xml/xml_templates/Role.xml +1 -0
  213. data/lib/cloud/vcloud/xml/xml_templates/RoleRecord.xml +1 -0
  214. data/lib/cloud/vcloud/xml/xml_templates/RoleReference.xml +1 -0
  215. data/lib/cloud/vcloud/xml/xml_templates/RoleReferences.xml +1 -0
  216. data/lib/cloud/vcloud/xml/xml_templates/RuntimeInfoSection.xml +1 -0
  217. data/lib/cloud/vcloud/xml/xml_templates/ScreenTicket.xml +1 -0
  218. data/lib/cloud/vcloud/xml/xml_templates/Session.xml +1 -0
  219. data/lib/cloud/vcloud/xml/xml_templates/ShadowVMReferences.xml +1 -0
  220. data/lib/cloud/vcloud/xml/xml_templates/StaticRoutingService.xml +1 -0
  221. data/lib/cloud/vcloud/xml/xml_templates/StrandedUserRecord.xml +1 -0
  222. data/lib/cloud/vcloud/xml/xml_templates/Task.xml +0 -0
  223. data/lib/cloud/vcloud/xml/xml_templates/TaskRecord.xml +1 -0
  224. data/lib/cloud/vcloud/xml/xml_templates/TaskReference.xml +1 -0
  225. data/lib/cloud/vcloud/xml/xml_templates/TaskReferences.xml +1 -0
  226. data/lib/cloud/vcloud/xml/xml_templates/TasksList.xml +1 -0
  227. data/lib/cloud/vcloud/xml/xml_templates/UndeployVAppParams.xml +1 -0
  228. data/lib/cloud/vcloud/xml/xml_templates/UploadVAppTemplateParams.xml +1 -0
  229. data/lib/cloud/vcloud/xml/xml_templates/User.xml +1 -0
  230. data/lib/cloud/vcloud/xml/xml_templates/UserRecord.xml +1 -0
  231. data/lib/cloud/vcloud/xml/xml_templates/UserReference.xml +1 -0
  232. data/lib/cloud/vcloud/xml/xml_templates/UserReferences.xml +1 -0
  233. data/lib/cloud/vcloud/xml/xml_templates/VApp.xml +1 -0
  234. data/lib/cloud/vcloud/xml/xml_templates/VAppLeaseSettings.xml +1 -0
  235. data/lib/cloud/vcloud/xml/xml_templates/VAppNetwork.xml +1 -0
  236. data/lib/cloud/vcloud/xml/xml_templates/VAppNetworkRecord.xml +1 -0
  237. data/lib/cloud/vcloud/xml/xml_templates/VAppNetworkReference.xml +1 -0
  238. data/lib/cloud/vcloud/xml/xml_templates/VAppNetworkReferences.xml +1 -0
  239. data/lib/cloud/vcloud/xml/xml_templates/VAppOrgNetworkRelationRecord.xml +1 -0
  240. data/lib/cloud/vcloud/xml/xml_templates/VAppOrgNetworkRelationReference.xml +1 -0
  241. data/lib/cloud/vcloud/xml/xml_templates/VAppOrgNetworkRelationReferences.xml +1 -0
  242. data/lib/cloud/vcloud/xml/xml_templates/VAppRecord.xml +1 -0
  243. data/lib/cloud/vcloud/xml/xml_templates/VAppReference.xml +1 -0
  244. data/lib/cloud/vcloud/xml/xml_templates/VAppReferences.xml +1 -0
  245. data/lib/cloud/vcloud/xml/xml_templates/VAppTemplate.xml +1 -0
  246. data/lib/cloud/vcloud/xml/xml_templates/VAppTemplateRecord.xml +1 -0
  247. data/lib/cloud/vcloud/xml/xml_templates/VAppTemplateReference.xml +1 -0
  248. data/lib/cloud/vcloud/xml/xml_templates/VAppTemplateReferences.xml +1 -0
  249. data/lib/cloud/vcloud/xml/xml_templates/VCloud.xml +1 -0
  250. data/lib/cloud/vcloud/xml/xml_templates/VMRecord.xml +1 -0
  251. data/lib/cloud/vcloud/xml/xml_templates/VMReference.xml +1 -0
  252. data/lib/cloud/vcloud/xml/xml_templates/VMReferences.xml +1 -0
  253. data/lib/cloud/vcloud/xml/xml_templates/VMWProviderVdcRecord.xml +1 -0
  254. data/lib/cloud/vcloud/xml/xml_templates/VMWProviderVdcReference.xml +1 -0
  255. data/lib/cloud/vcloud/xml/xml_templates/VMWProviderVdcReferences.xml +1 -0
  256. data/lib/cloud/vcloud/xml/xml_templates/Vdc.xml +1 -0
  257. data/lib/cloud/vcloud/xml/xml_templates/VdcReferences.xml +1 -0
  258. data/lib/cloud/vcloud/xml/xml_templates/VdcStorageProfile.xml +1 -0
  259. data/lib/cloud/vcloud/xml/xml_templates/VirtualCenterRecord.xml +1 -0
  260. data/lib/cloud/vcloud/xml/xml_templates/VirtualCenterReference.xml +1 -0
  261. data/lib/cloud/vcloud/xml/xml_templates/VirtualCenterReferences.xml +1 -0
  262. data/lib/cloud/vcloud/xml/xml_templates/Vm.xml +1 -0
  263. data/lib/cloud/vcloud/xml/xml_templates/VmPendingQuestion.xml +1 -0
  264. data/lib/cloud/vcloud/xml/xml_templates/VmQuestionAnswer.xml +1 -0
  265. data/lib/cloud/vcloud/xml/xml_templates/generate_dictionary.rb +8 -0
  266. data/lib/cloud/vcloud.rb +3 -7
  267. metadata +384 -88
  268. data/README +0 -26
  269. data/Rakefile +0 -50
  270. data/lib/cloud/vcloud/const.rb +0 -27
  271. data/lib/cloud/vcloud/util.rb +0 -23
  272. data/spec/assets/test-deployment-manifest.yml +0 -183
  273. data/spec/assets/test-director-config.yml +0 -73
  274. data/spec/assets/valid_stemcell.tgz +0 -0
  275. data/spec/spec_helper.rb +0 -135
  276. data/spec/unit/cloud_spec.rb +0 -506
@@ -1,16 +1,9 @@
1
- $: << File.expand_path(File.dirname(__FILE__))
1
+ require 'securerandom'
2
+ require 'logger'
2
3
 
3
- require "ruby_vcloud_sdk"
4
- require "cloud/vcloud/const"
5
- require "cloud/vcloud/util"
6
-
7
- require "digest/sha1"
8
- require "fileutils"
9
- require "logger"
10
- require "uuidtools"
11
- require "yajl"
12
- require "const"
13
- require "thread"
4
+ require_relative 'errors'
5
+ require_relative 'vcd_client'
6
+ require_relative 'steps'
14
7
 
15
8
  module VCloudCloud
16
9
 
@@ -18,616 +11,341 @@ module VCloudCloud
18
11
 
19
12
  def initialize(options)
20
13
  @logger = Bosh::Clouds::Config.logger
21
- VCloudSdk::Config.configure({ "logger" => @logger })
22
- @logger.debug("Input cloud options: #{options.inspect}")
23
-
24
- @agent_properties = options["agent"]
25
- vcds = options["vcds"]
26
- raise ArgumentError, "Invalid number of VCDs" unless vcds.size == 1
27
- @vcd = vcds[0]
14
+ @logger.debug "Input cloud options: #{options.inspect}"
28
15
 
29
- finalize_options
30
- @control = @vcd["control"]
31
- @retries = @control["retries"]
32
- @logger.info("VCD cloud options: #{options.inspect}")
16
+ @agent_properties = options['agent'] || {}
33
17
 
34
- @client_lock = Mutex.new
18
+ vcds = options['vcds']
19
+ raise ArgumentError, 'Invalid number of VCDs' unless vcds && vcds.size == 1
20
+ @vcd = vcds[0]
35
21
 
36
- at_exit { destroy_client }
37
- end
22
+ @entities = @vcd['entities']
23
+ raise ArgumentError, 'Invalid entities in VCD settings' unless @entities && @entities.is_a?(Hash)
38
24
 
39
- def client
40
- @client_lock.synchronize {
41
- if @client.nil?
42
- create_client
43
- else
44
- begin
45
- @client.get_ovdc
46
- @client
47
- rescue VCloudSdk::CloudError => e
48
- log_exception("validate, creating new session.", e)
49
- create_client
50
- end
51
- end
52
- }
25
+ @client_lock = Mutex.new # lock for establishing client connection
26
+ @vapp_lock = Mutex.new # lock for recompose vApp and delete vm from vApp
53
27
  end
54
28
 
55
29
  def create_stemcell(image, _)
56
- @client = client
57
-
58
- with_thread_name("create_stemcell(#{image}, _)") do
59
- @logger.debug("create_stemcell #{image} #{_}")
60
- result = nil
61
- Dir.mktmpdir do |temp_dir|
62
- @logger.info("Extracting stemcell to: #{temp_dir}")
63
- output = `tar -C #{temp_dir} -xzf #{image} 2>&1`
64
- raise "Corrupt image, tar exit status: #{$?.exitstatus} output:" +
65
- "#{output}" if $?.exitstatus != 0
66
-
67
- ovf_file = Dir.entries(temp_dir).find {
68
- |entry| File.extname(entry) == ".ovf" }
69
- raise "Missing OVF" unless ovf_file
70
- ovf_file = File.join(temp_dir, ovf_file)
71
-
72
- name = "sc-#{generate_unique_name}"
73
- @logger.info("Generated name: #{name}")
74
-
75
- @logger.info("Uploading #{ovf_file}")
76
- result = @client.upload_vapp_template(name, temp_dir).urn
77
- end
78
-
79
- @logger.info("Stemcell created as catalog vApp with ID #{result}.")
80
- result
81
- end
30
+ (steps "create_stemcell(#{image}, _)" do |s|
31
+ s.next Steps::StemcellInfo, image
32
+ s.next Steps::CreateTemplate, "sc-#{unique_name}"
33
+ s.next Steps::UploadTemplateFiles
34
+ s.next Steps::AddCatalogItem, :vapp, s.state[:vapp_template]
35
+ end)[:catalog_item].urn
82
36
  end
83
37
 
84
38
  def delete_stemcell(catalog_vapp_id)
85
- @client = client
86
-
87
- with_thread_name("delete_stemcell(#{catalog_vapp_id})") do
88
- @logger.debug("delete_stemcell #{catalog_vapp_id}")
89
-
90
- # shadow VMs (stemcell replicas) get deleted serially,
91
- # and upon failure to delete they must be deleted manually
92
- # from VCD "stranded items"
93
- @client.delete_catalog_vapp(catalog_vapp_id)
39
+ steps "delete_stemcell(#{catalog_vapp_id})" do |s|
40
+ catalog_vapp = client.resolve_entity catalog_vapp_id
41
+ raise "Catalog vApp #{catalog_vapp_id} not found" unless catalog_vapp
42
+ vapp = client.resolve_link catalog_vapp.entity
43
+ client.wait_entity vapp, true
44
+ client.invoke :delete, vapp.remove_link
45
+ client.invoke :delete, catalog_vapp.href
94
46
  end
95
47
  end
96
48
 
97
- def reconfigure_vm(vapp, resource_pool, networks, environment)
98
- vm = get_vm(vapp)
99
- ram_mb = Integer(resource_pool["ram"])
100
- cpu = Integer(resource_pool["cpu"])
101
- disk_mb = Integer(resource_pool["disk"])
102
-
103
- disks = vm.hardware_section.hard_disks
104
- @logger.debug("disks = #{disks.inspect}")
105
- raise IndexError, "Invalid number of VM hard disks" unless disks.size == 1
106
- system_disk = disks[0]
107
- disks_previous = Array.new(disks)
108
-
109
- add_vapp_networks(vapp, networks)
110
-
111
- @logger.info("Reconfiguring VM hardware: #{ram_mb} MB RAM, #{cpu} CPU, " +
112
- "#{disk_mb} MB disk, #{networks}.")
113
- @client.reconfigure_vm(vm) do |v|
114
- v.name = vapp.name
115
- v.description = @vcd["entities"]["description"]
116
- v.change_cpu_count(cpu)
117
- v.change_memory(ram_mb)
118
- v.add_hard_disk(disk_mb)
119
- v.delete_nic(*vm.hardware_section.nics)
120
- add_vm_nics(v, networks)
121
- end
49
+ def create_vm(agent_id, catalog_vapp_id, resource_pool, networks, disk_locality = nil, environment = nil)
50
+ (steps "create_vm(#{agent_id}, #{catalog_vapp_id}, #{resource_pool}, ...)" do |s|
51
+ # disk_locality should be an array of disk ids
52
+ disk_locality = independent_disks disk_locality
53
+
54
+ # agent_id is used as vm name
55
+ description = @entities['description']
56
+
57
+ requested_name = environment && environment['vapp']
58
+ vapp_name = requested_name ? "vapp-tmp-#{unique_name}" : agent_id
59
+
60
+ s.next Steps::Instantiate, catalog_vapp_id, vapp_name, description, disk_locality
61
+ client.flush_cache # flush cached vdc which contains vapp list
62
+ vapp = s.state[:vapp]
63
+ vm = s.state[:vm] = vapp.vms[0]
64
+
65
+ # save original disk configuration
66
+ s.state[:disks] = Array.new(vm.hardware_section.hard_disks)
67
+ reconfigure_vm s, agent_id, description, resource_pool, networks
68
+
69
+ vapp, vm =[s.state[:vapp], s.state[:vm]]
70
+
71
+ # To handle concurrent create_vm requests,
72
+ # if the target vApp exists, creates a temp vApp, and then recomposes its VM to the target vApp.
73
+ if requested_name
74
+ container_vapp = nil
75
+ vm_href = nil
76
+ existing_vm_hrefs = []
77
+
78
+ # VM is added to the target vApp sequentially.
79
+ @vapp_lock.synchronize do
80
+ begin
81
+ @logger.debug "Requesting container vApp: #{requested_name}"
82
+ container_vapp = client.vapp_by_name requested_name
83
+ rescue ObjectNotFoundError
84
+ # ignored, keep container_vapp nil
85
+ @logger.debug "Invalid container vApp: #{requested_name}"
86
+ end
87
+
88
+ if container_vapp
89
+ existing_vm_hrefs = container_vapp.vms.map { |v| v.href }
90
+ s.next Steps::Recompose, container_vapp.name, container_vapp, vm
91
+ client.flush_cache
92
+ vapp = client.reload vapp
93
+ client.wait_entity vapp
94
+ begin
95
+ s.next Steps::Delete, vapp, true
96
+ rescue => ex
97
+ @logger.warn "Caught exception when trying to delete tmp vapp #{vapp.name}: #{ex.to_s}"
98
+ end
99
+ else
100
+ # just rename the vApp
101
+ container_vapp = vapp
102
+ s.next Steps::Recompose, requested_name, container_vapp
103
+ end
104
+
105
+ # reload all the stuff
106
+ client.flush_cache
107
+ vapp = client.reload container_vapp
108
+ client.wait_entity vapp
109
+ vm_href = vapp.vms.map { |v| v.href } - existing_vm_hrefs
110
+ end
122
111
 
123
- delete_vapp_networks(vapp, networks)
112
+ raise "New virtual machine not found in recomposed vApp" if vm_href.empty?
113
+ s.state[:vm] = client.resolve_link vm_href[0]
114
+ end
124
115
 
125
- vapp, vm = get_vapp_vm_by_vapp_id(vapp.urn)
126
- ephemeral_disk = get_newly_added_disk(vm, disks_previous)
116
+ # create env and generate env ISO image
117
+ s.state[:env_metadata_key] = @entities['vm_metadata_key']
118
+ s.next Steps::CreateOrUpdateAgentEnv, networks, environment, @agent_properties
127
119
 
128
- # prepare guest customization settings
129
- network_env = generate_network_env(vm.hardware_section.nics, networks)
130
- disk_env = generate_disk_env(system_disk, ephemeral_disk)
131
- env = generate_agent_env(vapp.name, vm, vapp.name, network_env, disk_env)
132
- env["env"] = environment
133
- @logger.info("Setting VM env: #{vapp.urn} #{env.inspect}")
134
- set_agent_env(vm, env)
120
+ # TODO refact this
121
+ if requested_name
122
+ @vapp_lock.synchronize do
123
+ save_agent_env s
124
+ s.next Steps::PowerOn, :vm
125
+ end
126
+ else
127
+ save_agent_env s
128
+ s.next Steps::PowerOn, :vm
129
+ end
135
130
 
136
- @logger.info("Powering on vApp: #{vapp.urn}")
137
- @client.power_on_vapp(vapp)
138
- rescue VCloudSdk::CloudError
139
- delete_vm(vapp.urn)
140
- raise
131
+ # Update state to point to the correct vapp instead of the newly created temporary vapp for transition
132
+ # We do this as the final step to avoid problems such as rollback of Steps::Instantiate, which deletes state[:vapp]
133
+ s.state[:vapp] = vapp
134
+ s.state
135
+ end)[:vm].urn
141
136
  end
142
137
 
143
- def create_vm(agent_id, catalog_vapp_id, resource_pool, networks,
144
- disk_locality = nil, environment = {})
145
- @client = client
146
-
147
- with_thread_name("create_vm(#{agent_id}, ...)") do
148
- Util.retry_operation("create_vm(#{agent_id}, ...)", @retries["cpi"],
149
- @control["backoff"]) do
150
- @logger.info("Creating VM: #{agent_id}")
151
- @logger.debug("networks: #{networks.inspect}")
152
-
153
- locality = independent_disks(disk_locality)
154
-
155
- vapp = @client.instantiate_vapp_template(
156
- catalog_vapp_id, agent_id, # vapp name
157
- @vcd["entities"]["description"], locality)
158
- @logger.debug("Instantiated vApp: id=#{vapp.urn} name=#{vapp.name}")
138
+ def reboot_vm(vm_id)
139
+ steps "reboot_vm(#{vm_id})" do |s|
140
+ vm = s.state[:vm] = client.resolve_entity(vm_id)
159
141
 
160
- reconfigure_vm(vapp, resource_pool, networks, environment)
161
-
162
- @logger.info("Created VM: #{agent_id} as #{vapp.urn}")
163
- vapp.urn
164
- end
165
- end
166
- rescue VCloudSdk::CloudError => e
167
- log_exception("create vApp", e)
168
- raise e
169
- end
170
-
171
- def delete_vm(vapp_id)
172
- @client = client
173
-
174
- with_thread_name("delete_vm(#{vapp_id}, ...)") do
175
- Util.retry_operation("delete_vm(#{vapp_id}, ...)", @retries["cpi"],
176
- @control["backoff"]) do
177
- @logger.info("Deleting vApp: #{vapp_id}")
178
- vapp = @client.get_vapp(vapp_id)
179
- vm = get_vm(vapp)
180
- vm_name = vm.name
181
-
182
- begin
183
- @client.power_off_vapp(vapp)
184
- rescue VCloudSdk::VappSuspendedError => e
185
- @client.discard_suspended_state_vapp(vapp)
186
- @client.power_off_vapp(vapp)
142
+ @vapp_lock.synchronize do
143
+ if vm['status'] == VCloudSdk::Xml::RESOURCE_ENTITY_STATUS[:SUSPENDED].to_s
144
+ s.next Steps::DiscardSuspendedState, :vm
145
+ s.next Steps::PowerOn, :vm
146
+ elsif vm['status'] == VCloudSdk::Xml::RESOURCE_ENTITY_STATUS[:POWERED_OFF].to_s
147
+ s.next Steps::PowerOn, :vm
148
+ else
149
+ begin
150
+ s.next Steps::Reboot, :vm
151
+ rescue => ex
152
+ @logger.warn "Caught exception when trying to Reboot vm #{vm_id}: #{ex.to_s}"
153
+ @logger.debug 'Force a hard-reboot when failed to perform a soft-reboot'
154
+ s.next Steps::PowerOff, :vm, true
155
+ s.next Steps::PowerOn, :vm
156
+ end
187
157
  end
188
- del_vapp = @vcd["debug"]["delete_vapp"]
189
- @client.delete_vapp(vapp) if del_vapp
190
- @logger.info("Deleting ISO #{vm_name}")
191
- @client.delete_catalog_media(vm_name) if del_vapp
192
- @logger.info("Deleted vApp: #{vapp_id}")
193
158
  end
194
159
  end
195
- rescue VCloudSdk::CloudError => e
196
- log_exception("delete vApp #{vapp_id}", e)
197
- raise e
198
160
  end
199
161
 
200
- def reboot_vm(vapp_id)
201
- @client = client
202
-
203
- with_thread_name("reboot_vm(#{vapp_id}, ...)") do
204
- Util.retry_operation("reboot_vm(#{vapp_id}, ...)", @retries["cpi"],
205
- @control["backoff"]) do
206
- @logger.info("Rebooting vApp: #{vapp_id}")
207
- vapp = @client.get_vapp(vapp_id)
208
- begin
209
- @client.reboot_vapp(vapp)
210
- rescue VCloudSdk::VappPoweredOffError => e
211
- @client.power_on_vapp(vapp)
212
- rescue VCloudSdk::VappSuspendedError => e
213
- @client.discard_suspended_state_vapp(vapp)
214
- @client.power_on_vapp(vapp)
215
- end
216
- @logger.info("Rebooted vApp: #{vapp_id}")
217
- end
218
- end
219
- rescue VCloudSdk::CloudError => e
220
- log_exception("reboot vApp #{vapp_id}", e)
221
- raise e
162
+ def has_vm?(vm_id)
163
+ vm = client.resolve_entity vm_id
164
+ vm.type == VCloudSdk::Xml::MEDIA_TYPE[:VM]
165
+ rescue RestClient::Exception # invalid ID will get 403
166
+ false
167
+ rescue ObjectNotFoundError
168
+ false
222
169
  end
223
170
 
224
- def configure_networks(vapp_id, networks)
225
- @client = client
226
-
227
- with_thread_name("configure_networks(#{vapp_id}, ...)") do
228
- Util.retry_operation("configure_networks(#{vapp_id}, ...)",
229
- @retries["cpi"], @control["backoff"]) do
230
- @logger.info("Reconfiguring vApp networks: #{vapp_id}")
231
- vapp, vm = get_vapp_vm_by_vapp_id(vapp_id)
232
- @logger.debug("Powering off #{vapp.name}.")
233
- begin
234
- @client.power_off_vapp(vapp)
235
- rescue VCloudSdk::VappSuspendedError => e
236
- @client.discard_suspended_state_vapp(vapp)
237
- @client.power_off_vapp(vapp)
238
- end
171
+ def delete_vm(vm_id)
172
+ steps "delete_vm(#{vm_id})" do |s|
173
+ vm = s.state[:vm] = client.resolve_entity vm_id
174
+
175
+ @vapp_lock.synchronize do
176
+ # poweroff vm before we are able to delete it
177
+ s.next Steps::PowerOff, :vm, true
239
178
 
240
- add_vapp_networks(vapp, networks)
241
- @client.reconfigure_vm(vm) do |v|
242
- v.delete_nic(*vm.hardware_section.nics)
243
- add_vm_nics(v, networks)
179
+ vapp = s.state[:vapp] = client.resolve_link vm.container_vapp_link
180
+ if vapp.vms.size == 1
181
+ # Hack: if vApp is running, and the last VM is deleted, it is no longer stoppable and removable
182
+ # even from dashboard. So if there's only one VM, just stop and delete the vApp
183
+ s.next Steps::PowerOff, :vapp, true
184
+ s.next Steps::Undeploy, :vapp
185
+ s.next Steps::Delete, s.state[:vapp], true
186
+ else
187
+ s.next Steps::Undeploy, :vm
188
+ s.next Steps::Delete, s.state[:vm], true
244
189
  end
245
- delete_vapp_networks(vapp, networks)
246
-
247
- vapp, vm = get_vapp_vm_by_vapp_id(vapp_id)
248
- env = get_current_agent_env(vm)
249
- env["networks"] = generate_network_env(vm.hardware_section.nics,
250
- networks)
251
- @logger.debug("Updating agent env to: #{env.inspect}")
252
- set_agent_env(vm, env)
253
-
254
- @logger.debug("Powering #{vapp.name} back on.")
255
- @client.power_on_vapp(vapp)
256
- @logger.info("Configured vApp networks: #{vapp}")
257
190
  end
191
+
192
+ s.next Steps::DeleteCatalogMedia, vm.name
258
193
  end
259
- rescue VCloudSdk::CloudError => e
260
- log_exception("configure vApp networks: #{vapp}", e)
261
- raise e
262
194
  end
263
195
 
264
- def attach_disk(vapp_id, disk_id)
265
- @client = client
196
+ def configure_networks(vm_id, networks)
197
+ steps "configure_networks(#{vm_id}, #{networks})" do |s|
198
+ vm = s.state[:vm] = client.resolve_entity vm_id
266
199
 
267
- with_thread_name("attach_disk(#{vapp_id} #{disk_id})") do
268
- Util.retry_operation("attach_disk(#{vapp_id}, #{disk_id})",
269
- @retries["cpi"], @control["backoff"]) do
270
- @logger.info("Attaching disk: #{disk_id} on vm: #{vapp_id}")
200
+ @vapp_lock.synchronize do
201
+ # power off vm first
202
+ s.next Steps::PowerOff, :vm, true
271
203
 
272
- vapp, vm = get_vapp_vm_by_vapp_id(vapp_id)
273
- # vm.hardware_section will change, save current state of disks
274
- disks_previous = Array.new(vm.hardware_section.hard_disks)
204
+ # load container vApp
205
+ s.state[:vapp] = client.resolve_link vm.container_vapp_link
275
206
 
276
- disk = @client.get_disk(disk_id)
277
- @client.attach_disk(disk, vm)
207
+ reconfigure_vm s, nil, nil, nil, networks
278
208
 
279
- vapp, vm = get_vapp_vm_by_vapp_id(vapp_id)
280
- persistent_disk = get_newly_added_disk(vm, disks_previous)
209
+ # update environment
210
+ s.state[:env_metadata_key] = @entities['vm_metadata_key']
211
+ s.next Steps::LoadAgentEnv
212
+ vm = s.state[:vm] = client.reload vm
213
+ Steps::CreateOrUpdateAgentEnv.update_network_env s.state[:env], vm, networks
281
214
 
282
- env = get_current_agent_env(vm)
283
- env["disks"]["persistent"][disk_id] = persistent_disk.disk_id
284
- @logger.info("Updating agent env to: #{env.inspect}")
285
- set_agent_env(vm, env)
215
+ save_agent_env s
286
216
 
287
- @logger.info("Attached disk:#{disk_id} to VM:#{vapp_id}")
217
+ # power on
218
+ s.next Steps::PowerOn, :vm
288
219
  end
289
220
  end
290
- rescue VCloudSdk::CloudError => e
291
- log_exception("attach disk", e)
292
- raise e
293
221
  end
294
222
 
295
- def detach_disk(vapp_id, disk_id)
296
- @client = client
223
+ def create_disk(size_mb, vm_locality = nil)
224
+ (steps "create_disk(#{size_mb}, #{vm_locality.inspect})" do |s|
225
+ # vm_locality is used as vm_id
226
+ vm = vm_locality.nil? ? nil : client.resolve_entity(vm_locality)
227
+ s.next Steps::CreateDisk, unique_name, size_mb, vm
228
+ end)[:disk].urn
229
+ end
230
+
231
+ def attach_disk(vm_id, disk_id)
232
+ steps "attach_disk(#{vm_id}, #{disk_id})" do |s|
233
+ vm = s.state[:vm] = client.resolve_entity vm_id
297
234
 
298
- with_thread_name("detach_disk(#{vapp_id} #{disk_id})") do
299
- Util.retry_operation("detach_disk(#{vapp_id}, #{disk_id})",
300
- @retries["cpi"], @control["backoff"]) do
301
- @logger.info("Detaching disk: #{disk_id} from vm: #{vapp_id}")
235
+ # vm.hardware_section will change, save current state of disks
236
+ previous_disks_list = Array.new(vm.hardware_section.hard_disks)
302
237
 
303
- vapp, vm = get_vapp_vm_by_vapp_id(vapp_id)
238
+ s.state[:disk] = client.resolve_entity disk_id
304
239
 
305
- disk = @client.get_disk(disk_id)
306
- begin
307
- @client.detach_disk(disk, vm)
308
- rescue VCloudSdk::VmSuspendedError => e
309
- @client.discard_suspended_state_vapp(vapp)
310
- @client.detach_disk(disk, vm)
311
- end
240
+ @vapp_lock.synchronize do
241
+ s.next Steps::AttachDetachDisk, :attach
312
242
 
313
- env = get_current_agent_env(vm)
314
- env["disks"]["persistent"].delete(disk_id)
315
- @logger.info("Updating agent env to: #{env.inspect}")
316
- set_agent_env(vm, env)
243
+ # update environment
244
+ s.state[:env_metadata_key] = @entities['vm_metadata_key']
245
+ s.next Steps::LoadAgentEnv
317
246
 
318
- @logger.info("Detached disk: #{disk_id} on vm: #{vapp_id}")
247
+ vm = s.state[:vm] = client.reload vm
248
+ Steps::CreateOrUpdateAgentEnv.update_persistent_disk s.state[:env], vm, disk_id , previous_disks_list
249
+
250
+ save_agent_env s
319
251
  end
320
252
  end
321
- rescue VCloudSdk::CloudError => e
322
- log_exception("detach disk", e)
323
- raise e
324
253
  end
325
254
 
326
- def create_disk(size_mb, vm_locality = nil)
327
- @client = client
328
-
329
- with_thread_name("create_disk(#{size_mb}, vm_locality)") do
330
- Util.retry_operation("create_disk(#{size_mb}, vm_locality)",
331
- @retries["cpi"], @control["backoff"]) do
332
- @logger.info("Create disk: #{size_mb}, #{vm_locality}")
333
- disk_name = "#{generate_unique_name}"
334
- disk = nil
335
- if vm_locality.nil?
336
- @logger.info("Creating disk: #{disk_name} #{size_mb}")
337
- disk = @client.create_disk(disk_name, size_mb)
338
- else
339
- # vm_locality => vapp_id
340
- vapp, vm = get_vapp_vm_by_vapp_id(vm_locality)
341
- @logger.info("Creating disk: #{disk_name} #{size_mb} #{vm.name}")
342
- disk = @client.create_disk(disk_name, size_mb, vm)
255
+ def detach_disk(vm_id, disk_id)
256
+ steps "detach_disk(#{vm_id}, #{disk_id})" do |s|
257
+ vm = s.state[:vm] = client.resolve_entity vm_id
258
+ s.state[:disk] = client.resolve_entity disk_id
259
+ # if disk is not attached, just ignore
260
+ next unless vm.find_attached_disk s.state[:disk]
261
+
262
+ @vapp_lock.synchronize do
263
+ if vm['status'] == VCloudSdk::Xml::RESOURCE_ENTITY_STATUS[:SUSPENDED].to_s
264
+ s.next Steps::DiscardSuspendedState, :vm
265
+ end
266
+ s.next Steps::AttachDetachDisk, :detach
267
+
268
+ # update environment
269
+ s.state[:env_metadata_key] = @entities['vm_metadata_key']
270
+ s.next Steps::LoadAgentEnv
271
+ env = s.state[:env]
272
+ if env['disks'] && env['disks']['persistent'].is_a?(Hash)
273
+ env['disks']['persistent'].delete disk_id
343
274
  end
344
- @logger.info("Created disk: #{disk_name} #{disk.urn} #{size_mb} " +
345
- "#{vm_locality}")
346
- disk.urn
275
+
276
+ save_agent_env s
347
277
  end
348
278
  end
349
- rescue VCloudSdk::CloudError => e
350
- log_exception("create disk", e)
351
- raise e
352
279
  end
353
280
 
354
281
  def delete_disk(disk_id)
355
- @client = client
356
-
357
- with_thread_name("delete_disk(#{disk_id})") do
358
- Util.retry_operation("delete_disk(#{disk_id})", @retries["cpi"],
359
- @control["backoff"]) do
360
- @logger.info("Deleting disk: #{disk_id}")
361
- disk = @client.get_disk(disk_id)
362
- @client.delete_disk(disk)
363
- @logger.info("Deleted disk: #{disk_id}")
364
- end
282
+ steps "delete_disk(#{disk_id})" do |s|
283
+ disk = client.resolve_entity disk_id
284
+ s.next Steps::Delete, disk, true
365
285
  end
366
- rescue VCloudSdk::CloudError => e
367
- log_exception("delete disk", e)
368
- raise e
369
286
  end
370
287
 
371
288
  def get_disk_size_mb(disk_id)
372
- @client = client
373
-
374
- with_thread_name("get_disk_size(#{disk_id})") do
375
- Util.retry_operation("get_disk_size(#{disk_id})", @retries["cpi"],
376
- @control["backoff"]) do
377
- @logger.info("Getting disk size: #{disk_id}")
378
- disk = @client.get_disk(disk_id)
379
- @logger.info("Disk #{disk_id} size: #{disk.size_mb} MB")
380
- disk.size_mb
381
- end
382
- end
383
- rescue VCloudSdk::CloudError => e
384
- log_exception("get_disk_size", e)
385
- raise e
289
+ client.resolve_entity(disk_id).size_mb
386
290
  end
387
291
 
388
292
  def validate_deployment(old_manifest, new_manifest)
389
- # There is TODO in vSphere CPI that questions the necessity of this method
390
- raise NotImplementedError, "validate_deployment"
391
293
  end
392
294
 
393
295
  private
394
296
 
395
- def finalize_options
396
- @vcd["control"] = {} unless @vcd["control"]
397
- @vcd["control"]["retries"] = {} unless @vcd["control"]["retries"]
398
- @vcd["control"]["retries"]["default"] ||= RETRIES_DEFAULT
399
- @vcd["control"]["retries"]["upload_vapp_files"] ||=
400
- RETRIES_UPLOAD_VAPP_FILES
401
- @vcd["control"]["retries"]["cpi"] ||= RETRIES_CPI
402
- @vcd["control"]["delay"] ||= DELAY
403
- @vcd["control"]["time_limit_sec"] = {} unless
404
- @vcd["control"]["time_limit_sec"]
405
- @vcd["control"]["time_limit_sec"]["default"] ||= TIMELIMIT_DEFAULT
406
- @vcd["control"]["time_limit_sec"]["delete_vapp_template"] ||=
407
- TIMELIMIT_DELETE_VAPP_TEMPLATE
408
- @vcd["control"]["time_limit_sec"]["delete_vapp"] ||= TIMELIMIT_DELETE_VAPP
409
- @vcd["control"]["time_limit_sec"]["delete_media"] ||=
410
- TIMELIMIT_DELETE_MEDIA
411
- @vcd["control"]["time_limit_sec"]["instantiate_vapp_template"] ||=
412
- TIMELIMIT_INSTANTIATE_VAPP_TEMPLATE
413
- @vcd["control"]["time_limit_sec"]["power_on"] ||= TIMELIMIT_POWER_ON
414
- @vcd["control"]["time_limit_sec"]["power_off"] ||= TIMELIMIT_POWER_OFF
415
- @vcd["control"]["time_limit_sec"]["undeploy"] ||= TIMELIMIT_UNDEPLOY
416
- @vcd["control"]["time_limit_sec"]["process_descriptor_vapp_template"] ||=
417
- TIMELIMIT_PROCESS_DESCRIPTOR_VAPP_TEMPLATE
418
- @vcd["control"]["time_limit_sec"]["http_request"] ||=
419
- TIMELIMIT_HTTP_REQUEST
420
- @vcd["control"]["backoff"] ||= BACKOFF
421
- @vcd["control"]["rest_throttle"] = {} unless
422
- @vcd["control"]["rest_throttle"]
423
- @vcd["control"]["rest_throttle"]["min"] ||= REST_THROTTLE_MIN
424
- @vcd["control"]["rest_throttle"]["max"] ||= REST_THROTTLE_MAX
425
- @vcd["debug"] = {} unless @vcd["debug"]
426
- @vcd["debug"]["delete_vapp"] = DEBUG_DELETE_VAPP unless
427
- @vcd["debug"]["delete_vapp"]
428
- end
429
-
430
- def create_client
431
- url = @vcd["url"]
432
- @logger.debug("Create session to VCD cloud: #{url}")
433
-
434
- @client = VCloudSdk::Client.new(url, @vcd["user"],
435
- @vcd["password"], @vcd["entities"], @vcd["control"])
436
-
437
- @logger.info("Created session to VCD cloud: #{url}")
438
-
439
- @client
440
- rescue VCloudSdk::ApiError => e
441
- log_exception(e, "Failed to connect and establish session.")
442
- raise e
443
- end
444
-
445
- def destroy_client
446
- url = @vcd["url"]
447
- @logger.debug("Destroy session to VCD cloud: #{url}")
448
- # TODO VCloudSdk::Client should permit logout.
449
- @logger.info("Destroyed session to VCD cloud: #{url}")
450
- end
451
-
452
- def generate_unique_name
453
- UUIDTools::UUID.random_create.to_s
454
- end
455
-
456
- def log_exception(op, e)
457
- @logger.error("Failed to #{op}.")
458
- @logger.error(e)
459
- end
460
-
461
- def generate_network_env(nics, networks)
462
- nic_net = {}
463
- nics.each do |nic|
464
- nic_net[nic.network] = nic
465
- end
466
- @logger.debug("nic_net #{nic_net.inspect}")
467
-
468
- network_env = {}
469
- networks.each do |network_name, network|
470
- network_entry = network.dup
471
- v_network_name = network["cloud_properties"]["name"]
472
- nic = nic_net[v_network_name]
473
- if nic.nil? then
474
- @logger.warn("Not generating network env for #{v_network_name}")
475
- next
476
- end
477
- network_entry["mac"] = nic.mac_address
478
- network_env[network_name] = network_entry
297
+ def client
298
+ @client_lock.synchronize do
299
+ @client = VCloudClient.new(@vcd, @logger) if @client.nil?
479
300
  end
480
- network_env
481
- end
482
-
483
- def generate_disk_env(system_disk, ephemeral_disk)
484
- {
485
- "system" => system_disk.disk_id,
486
- "ephemeral" => ephemeral_disk.disk_id,
487
- "persistent" => {}
488
- }
301
+ @client
489
302
  end
490
303
 
491
- def generate_agent_env(name, vm, agent_id, networking_env, disk_env)
492
- vm_env = {
493
- "name" => name,
494
- "id" => vm.urn
495
- }
496
-
497
- env = {}
498
- env["vm"] = vm_env
499
- env["agent_id"] = agent_id
500
- env["networks"] = networking_env
501
- env["disks"] = disk_env
502
- env.merge!(@agent_properties)
304
+ def steps(name, options = {}, &block)
305
+ Transaction.perform name, client(), options, &block
503
306
  end
504
307
 
505
- def get_current_agent_env(vm)
506
- env = @client.get_metadata(vm, @vcd["entities"]["vm_metadata_key"])
507
- @logger.info("Current agent env: #{env.inspect}")
508
- Yajl::Parser.parse(env)
308
+ def unique_name
309
+ SecureRandom.uuid.to_s
509
310
  end
510
311
 
511
- def set_agent_env(vm, env)
512
- env_json = Yajl::Encoder.encode(env)
513
- @logger.debug("env.iso content #{env_json}")
514
-
515
- begin
516
- # Clear existing ISO if one exists.
517
- @logger.info("Ejecting ISO #{vm.name}")
518
- @client.eject_catalog_media(vm, vm.name)
519
- @logger.info("Deleting ISO #{vm.name}")
520
- @client.delete_catalog_media(vm.name)
521
- rescue VCloudSdk::ObjectNotFoundError
522
- @logger.debug("No ISO to eject/delete before setting new agent env.")
523
- # Continue setting agent env...
524
- end
525
-
526
- # generate env iso, and insert into VM
527
- Dir.mktmpdir do |path|
528
- env_path = File.join(path, "env")
529
- iso_path = File.join(path, "env.iso")
530
- File.open(env_path, "w") { |f| f.write(env_json) }
531
- output = `genisoimage -o #{iso_path} #{env_path} 2>&1`
532
- raise "#{$?.exitstatus} -#{output}" if $?.exitstatus != 0
533
-
534
- @client.set_metadata(vm, @vcd["entities"]["vm_metadata_key"], env_json)
535
-
536
- storage_profiles = @client.get_ovdc.storage_profiles || []
537
- media_storage_profile = storage_profiles.find { |sp| sp["name"] ==
538
- @vcd["entities"]["media_storage_profile"] }
539
- @logger.info("Uploading and inserting ISO #{iso_path} as #{vm.name} " +
540
- "to #{media_storage_profile.inspect}")
541
- @client.upload_catalog_media(vm.name, iso_path, media_storage_profile)
542
- @client.insert_catalog_media(vm, vm.name)
543
- @logger.info("Uploaded and inserted ISO #{iso_path} as #{vm.name}")
544
- end
545
- end
546
-
547
- def delete_vapp_networks(vapp, exclude_nets)
548
- exclude = exclude_nets.map { |k,v| v["cloud_properties"]["name"] }.uniq
549
- @client.delete_networks(vapp, exclude)
550
- @logger.debug("Deleted vApp #{vapp.name} networks excluding " +
551
- "#{exclude.inspect}.")
552
- end
553
-
554
- def add_vapp_networks(vapp, networks)
555
- @logger.debug("Networks to add: #{networks.inspect}")
556
- ovdc = @client.get_ovdc
557
- accessible_org_networks = ovdc.available_networks
558
- @logger.debug("Accessible Org nets: #{accessible_org_networks.inspect}")
559
-
560
- cloud_networks = networks.map { |k,v| v["cloud_properties"]["name"] }.uniq
561
- cloud_networks.each do |configured_network|
562
- @logger.debug("Adding configured network: #{configured_network}")
563
- org_net = accessible_org_networks.find {
564
- |n| n["name"] == configured_network }
565
- unless org_net
566
- raise VCloudSdk::CloudError, "Configured network: " +
567
- "#{configured_network}, is not accessible to VDC:#{ovdc.name}."
568
- end
569
- @logger.debug("Adding configured network: #{configured_network}, => " +
570
- "Org net:#{org_net.inspect} to vApp:#{vapp.name}.")
571
- @client.add_network(vapp, org_net)
572
- @logger.debug("Added vApp network: #{configured_network}.")
312
+ def independent_disks(disk_locality)
313
+ disk_locality ||= []
314
+ @logger.info "Instantiate vApp accessible to disks: #{disk_locality.join(',')}"
315
+ disk_locality.map do |disk_id|
316
+ client.resolve_entity disk_id
573
317
  end
574
- @logger.debug("Accessible configured networks added:#{networks.inspect}.")
575
318
  end
576
319
 
577
- def add_vm_nics(v, networks)
578
- networks.values.each_with_index do |network, nic_index|
579
- if nic_index + 1 >= VM_NIC_LIMIT then
580
- @logger.warn("Max number of NICs reached")
581
- break
582
- end
583
- configured_network = network["cloud_properties"]["name"]
584
- @logger.info("Adding NIC with IP address #{network["ip"]}.")
585
- v.add_nic(nic_index, configured_network,
586
- VCloudSdk::Xml::IP_ADDRESSING_MODE[:MANUAL], network["ip"])
587
- v.connect_nic(nic_index, configured_network,
588
- VCloudSdk::Xml::IP_ADDRESSING_MODE[:MANUAL], network["ip"])
589
- end
590
- @logger.info("NICs added to #{v.name} and connected to network:" +
591
- " #{networks.inspect}")
320
+ def network_names(networks)
321
+ networks.map { |k,v| v['cloud_properties']['name'] }.uniq
592
322
  end
593
323
 
594
- def get_vm(vapp)
595
- vms = vapp.vms
596
- raise IndexError, "Invalid number of vApp VMs" unless vms.size == 1
597
- vms[0]
324
+ def reconfigure_vm(s, name, description, resource_pool, networks)
325
+ net_names = network_names networks
326
+ s.next Steps::AddNetworks, net_names
327
+ s.next Steps::ReconfigureVM, name, description, resource_pool, networks
328
+ s.next Steps::DeleteUnusedNetworks, net_names
598
329
  end
599
330
 
600
- def get_vapp_vm_by_vapp_id(id)
601
- vapp = @client.get_vapp(id)
602
- [vapp, get_vm(vapp)]
603
- end
331
+ def save_agent_env(s)
332
+ s.next Steps::SaveAgentEnv
604
333
 
605
- def get_newly_added_disk(vm, disks_previous)
606
- disks_current = vm.hardware_section.hard_disks
607
- newly_added = disks_current - disks_previous
334
+ vm = s.state[:vm]
608
335
 
609
- if newly_added.size != 1
610
- @logger.debug("Previous disks in #{vapp_id}: #{disks_previous.inspect}")
611
- @logger.debug("Current disks in #{vapp_id}: #{disks_current.inspect}")
612
- raise IndexError, "Expecting #{disks_previous.size + 1} disks, found " +
613
- "#{disks_current.size}"
614
- end
336
+ # eject and delete old env ISO
337
+ s.next Steps::EjectCatalogMedia, vm.name
338
+ s.next Steps::DeleteCatalogMedia, vm.name
615
339
 
616
- @logger.info("Newly added disk: #{newly_added[0]}")
617
- newly_added[0]
618
- end
340
+ # attach new env ISO
341
+ storage_profiles = client.vdc.storage_profiles || []
342
+ media_storage_profile = storage_profiles.find { |sp| sp['name'] == @entities['media_storage_profile'] }
343
+ s.next Steps::CreateMedia, vm.name, s.state[:iso], 'iso', media_storage_profile
344
+ s.next Steps::UploadMediaFiles, s.state[:iso]
345
+ s.next Steps::AddCatalogItem, :media, s.state[:media]
346
+ s.next Steps::InsertCatalogMedia, vm.name
619
347
 
620
- def independent_disks(disk_locality)
621
- disk_locality ||= []
622
- @logger.info("Instantiate vApp accessible to disks: " +
623
- "#{disk_locality.join(",")}")
624
- disks = []
625
- disk_locality.each do |disk_id|
626
- disks << @client.get_disk(disk_id)
627
- end
628
- disks
348
+ s.state[:vm] = client.reload vm
629
349
  end
630
-
631
350
  end
632
-
633
351
  end