ruby_vcloud_sdk 0.4.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (319) hide show
  1. data/README +1 -0
  2. data/Rakefile +50 -0
  3. data/lib/ruby_vcloud_sdk.rb +19 -0
  4. data/lib/ruby_vcloud_sdk/client.rb +899 -0
  5. data/lib/ruby_vcloud_sdk/config.rb +17 -0
  6. data/lib/ruby_vcloud_sdk/connection/connection.rb +163 -0
  7. data/lib/ruby_vcloud_sdk/connection/file_uploader.rb +43 -0
  8. data/lib/ruby_vcloud_sdk/errors.rb +21 -0
  9. data/lib/ruby_vcloud_sdk/ovf_directory.rb +45 -0
  10. data/lib/ruby_vcloud_sdk/util.rb +21 -0
  11. data/lib/ruby_vcloud_sdk/version.rb +3 -0
  12. data/lib/ruby_vcloud_sdk/xml/constants.rb +427 -0
  13. data/lib/ruby_vcloud_sdk/xml/wrapper.rb +242 -0
  14. data/lib/ruby_vcloud_sdk/xml/wrapper_classes.rb +3 -0
  15. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/admin_catalog.rb +20 -0
  16. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/admin_org.rb +15 -0
  17. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/catalog_item.rb +27 -0
  18. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/disk.rb +40 -0
  19. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/disk_attach_or_detach_params.rb +12 -0
  20. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/disk_create_params.rb +47 -0
  21. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/entity.rb +11 -0
  22. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/file.rb +11 -0
  23. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/hard_disk_item_wrapper.rb +50 -0
  24. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/instantiate_vapp_template_params.rb +71 -0
  25. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/ip_scope.rb +55 -0
  26. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/item.rb +32 -0
  27. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/media.rb +53 -0
  28. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/media_insert_or_eject_params.rb +17 -0
  29. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/metadata_value.rb +15 -0
  30. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/network.rb +15 -0
  31. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/network_config.rb +27 -0
  32. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/network_config_section.rb +25 -0
  33. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/network_connection.rb +71 -0
  34. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/network_connection_section.rb +67 -0
  35. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/nic_item_wrapper.rb +91 -0
  36. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/org_network.rb +19 -0
  37. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/org_vdc_network.rb +11 -0
  38. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/session.rb +17 -0
  39. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/task.rb +32 -0
  40. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/upload_vapp_template_params.rb +11 -0
  41. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/vapp.rb +55 -0
  42. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/vapp_template.rb +19 -0
  43. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/vcloud.rb +15 -0
  44. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/vdc.rb +54 -0
  45. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/vdc_storage_profile.rb +15 -0
  46. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/virtual_hardware_section.rb +68 -0
  47. data/lib/ruby_vcloud_sdk/xml/wrapper_classes/vm.rb +179 -0
  48. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminAllocatedExtIpRecord.xml +1 -0
  49. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminCatalog.xml +1 -0
  50. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminCatalogItemRecord.xml +1 -0
  51. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminCatalogRecord.xml +1 -0
  52. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminGroupRecord.xml +1 -0
  53. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminMediaRecord.xml +1 -0
  54. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminOrg.xml +1 -0
  55. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminOrgNetworkRecord.xml +1 -0
  56. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminShadowVmRecord.xml +1 -0
  57. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminTaskRecord.xml +1 -0
  58. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminUserRecord.xml +1 -0
  59. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminVAppNetworkRecord.xml +1 -0
  60. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminVAppRecord.xml +1 -0
  61. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminVAppReference.xml +1 -0
  62. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminVAppReferences.xml +1 -0
  63. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminVAppTemplateRecord.xml +1 -0
  64. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminVdc.xml +1 -0
  65. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminVdcRecord.xml +1 -0
  66. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminVdcReference.xml +1 -0
  67. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminVdcReferences.xml +1 -0
  68. data/lib/ruby_vcloud_sdk/xml/xml_templates/AdminVmRecord.xml +1 -0
  69. data/lib/ruby_vcloud_sdk/xml/xml_templates/AllEULAsAccepted.xml +1 -0
  70. data/lib/ruby_vcloud_sdk/xml/xml_templates/AllocatedExtIpRecord.xml +1 -0
  71. data/lib/ruby_vcloud_sdk/xml/xml_templates/BlockingTaskRecord.xml +1 -0
  72. data/lib/ruby_vcloud_sdk/xml/xml_templates/BlockingTaskReference.xml +1 -0
  73. data/lib/ruby_vcloud_sdk/xml/xml_templates/BlockingTaskReferences.xml +1 -0
  74. data/lib/ruby_vcloud_sdk/xml/xml_templates/CaptureVAppParams.xml +1 -0
  75. data/lib/ruby_vcloud_sdk/xml/xml_templates/Catalog.xml +1 -0
  76. data/lib/ruby_vcloud_sdk/xml/xml_templates/CatalogItem.xml +1 -0
  77. data/lib/ruby_vcloud_sdk/xml/xml_templates/CatalogItemRecord.xml +1 -0
  78. data/lib/ruby_vcloud_sdk/xml/xml_templates/CatalogItemReference.xml +1 -0
  79. data/lib/ruby_vcloud_sdk/xml/xml_templates/CatalogItemReferences.xml +1 -0
  80. data/lib/ruby_vcloud_sdk/xml/xml_templates/CatalogRecord.xml +1 -0
  81. data/lib/ruby_vcloud_sdk/xml/xml_templates/CatalogReference.xml +1 -0
  82. data/lib/ruby_vcloud_sdk/xml/xml_templates/CatalogReferences.xml +1 -0
  83. data/lib/ruby_vcloud_sdk/xml/xml_templates/CellRecord.xml +1 -0
  84. data/lib/ruby_vcloud_sdk/xml/xml_templates/CloneMediaParams.xml +1 -0
  85. data/lib/ruby_vcloud_sdk/xml/xml_templates/CloneVAppParams.xml +1 -0
  86. data/lib/ruby_vcloud_sdk/xml/xml_templates/CloneVAppTemplateParams.xml +1 -0
  87. data/lib/ruby_vcloud_sdk/xml/xml_templates/ComposeVAppParams.xml +1 -0
  88. data/lib/ruby_vcloud_sdk/xml/xml_templates/ControlAccessParams.xml +1 -0
  89. data/lib/ruby_vcloud_sdk/xml/xml_templates/CustomizationSection.xml +1 -0
  90. data/lib/ruby_vcloud_sdk/xml/xml_templates/DatastoreProviderVdcRelationRecord.xml +1 -0
  91. data/lib/ruby_vcloud_sdk/xml/xml_templates/DatastoreRecord.xml +1 -0
  92. data/lib/ruby_vcloud_sdk/xml/xml_templates/DatastoreReference.xml +1 -0
  93. data/lib/ruby_vcloud_sdk/xml/xml_templates/DatastoreReferences.xml +1 -0
  94. data/lib/ruby_vcloud_sdk/xml/xml_templates/DeployVAppParams.xml +1 -0
  95. data/lib/ruby_vcloud_sdk/xml/xml_templates/DhcpService.xml +1 -0
  96. data/lib/ruby_vcloud_sdk/xml/xml_templates/DiskAttachOrDetachParams.xml +5 -0
  97. data/lib/ruby_vcloud_sdk/xml/xml_templates/DiskCreateParams.xml +9 -0
  98. data/lib/ruby_vcloud_sdk/xml/xml_templates/DvSwitchRecord.xml +1 -0
  99. data/lib/ruby_vcloud_sdk/xml/xml_templates/Entity.xml +1 -0
  100. data/lib/ruby_vcloud_sdk/xml/xml_templates/Error.xml +1 -0
  101. data/lib/ruby_vcloud_sdk/xml/xml_templates/EventRecord.xml +1 -0
  102. data/lib/ruby_vcloud_sdk/xml/xml_templates/ExternalNetwork.xml +1 -0
  103. data/lib/ruby_vcloud_sdk/xml/xml_templates/File.xml +1 -0
  104. data/lib/ruby_vcloud_sdk/xml/xml_templates/FirewallService.xml +1 -0
  105. data/lib/ruby_vcloud_sdk/xml/xml_templates/GeneralOrgSettings.xml +1 -0
  106. data/lib/ruby_vcloud_sdk/xml/xml_templates/Group.xml +1 -0
  107. data/lib/ruby_vcloud_sdk/xml/xml_templates/GroupRecord.xml +1 -0
  108. data/lib/ruby_vcloud_sdk/xml/xml_templates/GroupReference.xml +1 -0
  109. data/lib/ruby_vcloud_sdk/xml/xml_templates/GroupReferences.xml +1 -0
  110. data/lib/ruby_vcloud_sdk/xml/xml_templates/GuestCustomizationSection.xml +1 -0
  111. data/lib/ruby_vcloud_sdk/xml/xml_templates/HostRecord.xml +1 -0
  112. data/lib/ruby_vcloud_sdk/xml/xml_templates/HostReference.xml +1 -0
  113. data/lib/ruby_vcloud_sdk/xml/xml_templates/HostReferences.xml +1 -0
  114. data/lib/ruby_vcloud_sdk/xml/xml_templates/InstantiateOvfParams.xml +1 -0
  115. data/lib/ruby_vcloud_sdk/xml/xml_templates/InstantiateVAppTemplateParams.xml +1 -0
  116. data/lib/ruby_vcloud_sdk/xml/xml_templates/IpScope.xml +12 -0
  117. data/lib/ruby_vcloud_sdk/xml/xml_templates/IpsecVpnLocalPeer.xml +1 -0
  118. data/lib/ruby_vcloud_sdk/xml/xml_templates/IpsecVpnPeer.xml +1 -0
  119. data/lib/ruby_vcloud_sdk/xml/xml_templates/IpsecVpnRemotePeer.xml +1 -0
  120. data/lib/ruby_vcloud_sdk/xml/xml_templates/IpsecVpnService.xml +1 -0
  121. data/lib/ruby_vcloud_sdk/xml/xml_templates/IpsecVpnThirdPartyPeer.xml +1 -0
  122. data/lib/ruby_vcloud_sdk/xml/xml_templates/Item.xml +3 -0
  123. data/lib/ruby_vcloud_sdk/xml/xml_templates/ItemVcd.xml +5 -0
  124. data/lib/ruby_vcloud_sdk/xml/xml_templates/LeaseSettingsSection.xml +1 -0
  125. data/lib/ruby_vcloud_sdk/xml/xml_templates/Link.xml +1 -0
  126. data/lib/ruby_vcloud_sdk/xml/xml_templates/Media.xml +6 -0
  127. data/lib/ruby_vcloud_sdk/xml/xml_templates/MediaInsertOrEjectParams.xml +4 -0
  128. data/lib/ruby_vcloud_sdk/xml/xml_templates/MediaRecord.xml +1 -0
  129. data/lib/ruby_vcloud_sdk/xml/xml_templates/MediaReference.xml +1 -0
  130. data/lib/ruby_vcloud_sdk/xml/xml_templates/MediaReferences.xml +1 -0
  131. data/lib/ruby_vcloud_sdk/xml/xml_templates/Metadata.xml +5 -0
  132. data/lib/ruby_vcloud_sdk/xml/xml_templates/MetadataEntry.xml +7 -0
  133. data/lib/ruby_vcloud_sdk/xml/xml_templates/MetadataValue.xml +8 -0
  134. data/lib/ruby_vcloud_sdk/xml/xml_templates/NatService.xml +1 -0
  135. data/lib/ruby_vcloud_sdk/xml/xml_templates/Network.xml +4 -0
  136. data/lib/ruby_vcloud_sdk/xml/xml_templates/NetworkAssignment.xml +1 -0
  137. data/lib/ruby_vcloud_sdk/xml/xml_templates/NetworkConfig.xml +21 -0
  138. data/lib/ruby_vcloud_sdk/xml/xml_templates/NetworkConfigSection.xml +1 -0
  139. data/lib/ruby_vcloud_sdk/xml/xml_templates/NetworkConnection.xml +11 -0
  140. data/lib/ruby_vcloud_sdk/xml/xml_templates/NetworkConnectionSection.xml +1 -0
  141. data/lib/ruby_vcloud_sdk/xml/xml_templates/NetworkPoolRecord.xml +1 -0
  142. data/lib/ruby_vcloud_sdk/xml/xml_templates/NetworkPoolReference.xml +1 -0
  143. data/lib/ruby_vcloud_sdk/xml/xml_templates/NetworkPoolReferences.xml +1 -0
  144. data/lib/ruby_vcloud_sdk/xml/xml_templates/NetworkRecord.xml +1 -0
  145. data/lib/ruby_vcloud_sdk/xml/xml_templates/NetworkReference.xml +1 -0
  146. data/lib/ruby_vcloud_sdk/xml/xml_templates/NetworkReferences.xml +1 -0
  147. data/lib/ruby_vcloud_sdk/xml/xml_templates/NetworkService.xml +1 -0
  148. data/lib/ruby_vcloud_sdk/xml/xml_templates/Org.xml +1 -0
  149. data/lib/ruby_vcloud_sdk/xml/xml_templates/OrgEmailSettings.xml +1 -0
  150. data/lib/ruby_vcloud_sdk/xml/xml_templates/OrgList.xml +1 -0
  151. data/lib/ruby_vcloud_sdk/xml/xml_templates/OrgNetwork.xml +1 -0
  152. data/lib/ruby_vcloud_sdk/xml/xml_templates/OrgNetworkRecord.xml +1 -0
  153. data/lib/ruby_vcloud_sdk/xml/xml_templates/OrgNetworkReference.xml +1 -0
  154. data/lib/ruby_vcloud_sdk/xml/xml_templates/OrgNetworkReferences.xml +1 -0
  155. data/lib/ruby_vcloud_sdk/xml/xml_templates/OrgPasswordPolicySettings.xml +1 -0
  156. data/lib/ruby_vcloud_sdk/xml/xml_templates/OrgRecord.xml +1 -0
  157. data/lib/ruby_vcloud_sdk/xml/xml_templates/OrgReference.xml +1 -0
  158. data/lib/ruby_vcloud_sdk/xml/xml_templates/OrgReferences.xml +1 -0
  159. data/lib/ruby_vcloud_sdk/xml/xml_templates/OrgSettings.xml +1 -0
  160. data/lib/ruby_vcloud_sdk/xml/xml_templates/OrgVAppTemplateLeaseSettings.xml +1 -0
  161. data/lib/ruby_vcloud_sdk/xml/xml_templates/OrgVdcNetwork.xml +1 -0
  162. data/lib/ruby_vcloud_sdk/xml/xml_templates/OrgVdcRecord.xml +1 -0
  163. data/lib/ruby_vcloud_sdk/xml/xml_templates/OrgVdcReference.xml +1 -0
  164. data/lib/ruby_vcloud_sdk/xml/xml_templates/OrgVdcReferences.xml +1 -0
  165. data/lib/ruby_vcloud_sdk/xml/xml_templates/OrgVdcResourcePoolRelationRecord.xml +1 -0
  166. data/lib/ruby_vcloud_sdk/xml/xml_templates/Owner.xml +1 -0
  167. data/lib/ruby_vcloud_sdk/xml/xml_templates/PortgroupRecord.xml +1 -0
  168. data/lib/ruby_vcloud_sdk/xml/xml_templates/ProductSectionList.xml +1 -0
  169. data/lib/ruby_vcloud_sdk/xml/xml_templates/ProviderVdc.xml +1 -0
  170. data/lib/ruby_vcloud_sdk/xml/xml_templates/ProviderVdcResourcePoolRelationRecord.xml +1 -0
  171. data/lib/ruby_vcloud_sdk/xml/xml_templates/PublishCatalogParams.xml +1 -0
  172. data/lib/ruby_vcloud_sdk/xml/xml_templates/QueryList.xml +1 -0
  173. data/lib/ruby_vcloud_sdk/xml/xml_templates/QueryResultRecords.xml +1 -0
  174. data/lib/ruby_vcloud_sdk/xml/xml_templates/RasdItemsList.xml +1 -0
  175. data/lib/ruby_vcloud_sdk/xml/xml_templates/RecomposeVAppParams.xml +1 -0
  176. data/lib/ruby_vcloud_sdk/xml/xml_templates/Record.xml +1 -0
  177. data/lib/ruby_vcloud_sdk/xml/xml_templates/Reference.xml +1 -0
  178. data/lib/ruby_vcloud_sdk/xml/xml_templates/References.xml +1 -0
  179. data/lib/ruby_vcloud_sdk/xml/xml_templates/RelocateParams.xml +1 -0
  180. data/lib/ruby_vcloud_sdk/xml/xml_templates/ResourceEntity.xml +1 -0
  181. data/lib/ruby_vcloud_sdk/xml/xml_templates/ResourcePoolRecord.xml +1 -0
  182. data/lib/ruby_vcloud_sdk/xml/xml_templates/Right.xml +1 -0
  183. data/lib/ruby_vcloud_sdk/xml/xml_templates/RightRecord.xml +1 -0
  184. data/lib/ruby_vcloud_sdk/xml/xml_templates/RightReference.xml +1 -0
  185. data/lib/ruby_vcloud_sdk/xml/xml_templates/RightReferences.xml +1 -0
  186. data/lib/ruby_vcloud_sdk/xml/xml_templates/Role.xml +1 -0
  187. data/lib/ruby_vcloud_sdk/xml/xml_templates/RoleRecord.xml +1 -0
  188. data/lib/ruby_vcloud_sdk/xml/xml_templates/RoleReference.xml +1 -0
  189. data/lib/ruby_vcloud_sdk/xml/xml_templates/RoleReferences.xml +1 -0
  190. data/lib/ruby_vcloud_sdk/xml/xml_templates/RuntimeInfoSection.xml +1 -0
  191. data/lib/ruby_vcloud_sdk/xml/xml_templates/ScreenTicket.xml +1 -0
  192. data/lib/ruby_vcloud_sdk/xml/xml_templates/Session.xml +1 -0
  193. data/lib/ruby_vcloud_sdk/xml/xml_templates/ShadowVMReferences.xml +1 -0
  194. data/lib/ruby_vcloud_sdk/xml/xml_templates/StaticRoutingService.xml +1 -0
  195. data/lib/ruby_vcloud_sdk/xml/xml_templates/StrandedUserRecord.xml +1 -0
  196. data/lib/ruby_vcloud_sdk/xml/xml_templates/Task.xml +0 -0
  197. data/lib/ruby_vcloud_sdk/xml/xml_templates/TaskRecord.xml +1 -0
  198. data/lib/ruby_vcloud_sdk/xml/xml_templates/TaskReference.xml +1 -0
  199. data/lib/ruby_vcloud_sdk/xml/xml_templates/TaskReferences.xml +1 -0
  200. data/lib/ruby_vcloud_sdk/xml/xml_templates/TasksList.xml +1 -0
  201. data/lib/ruby_vcloud_sdk/xml/xml_templates/UndeployVAppParams.xml +1 -0
  202. data/lib/ruby_vcloud_sdk/xml/xml_templates/UploadVAppTemplateParams.xml +1 -0
  203. data/lib/ruby_vcloud_sdk/xml/xml_templates/User.xml +1 -0
  204. data/lib/ruby_vcloud_sdk/xml/xml_templates/UserRecord.xml +1 -0
  205. data/lib/ruby_vcloud_sdk/xml/xml_templates/UserReference.xml +1 -0
  206. data/lib/ruby_vcloud_sdk/xml/xml_templates/UserReferences.xml +1 -0
  207. data/lib/ruby_vcloud_sdk/xml/xml_templates/VApp.xml +1 -0
  208. data/lib/ruby_vcloud_sdk/xml/xml_templates/VAppLeaseSettings.xml +1 -0
  209. data/lib/ruby_vcloud_sdk/xml/xml_templates/VAppNetwork.xml +1 -0
  210. data/lib/ruby_vcloud_sdk/xml/xml_templates/VAppNetworkRecord.xml +1 -0
  211. data/lib/ruby_vcloud_sdk/xml/xml_templates/VAppNetworkReference.xml +1 -0
  212. data/lib/ruby_vcloud_sdk/xml/xml_templates/VAppNetworkReferences.xml +1 -0
  213. data/lib/ruby_vcloud_sdk/xml/xml_templates/VAppOrgNetworkRelationRecord.xml +1 -0
  214. data/lib/ruby_vcloud_sdk/xml/xml_templates/VAppOrgNetworkRelationReference.xml +1 -0
  215. data/lib/ruby_vcloud_sdk/xml/xml_templates/VAppOrgNetworkRelationReferences.xml +1 -0
  216. data/lib/ruby_vcloud_sdk/xml/xml_templates/VAppRecord.xml +1 -0
  217. data/lib/ruby_vcloud_sdk/xml/xml_templates/VAppReference.xml +1 -0
  218. data/lib/ruby_vcloud_sdk/xml/xml_templates/VAppReferences.xml +1 -0
  219. data/lib/ruby_vcloud_sdk/xml/xml_templates/VAppTemplate.xml +1 -0
  220. data/lib/ruby_vcloud_sdk/xml/xml_templates/VAppTemplateRecord.xml +1 -0
  221. data/lib/ruby_vcloud_sdk/xml/xml_templates/VAppTemplateReference.xml +1 -0
  222. data/lib/ruby_vcloud_sdk/xml/xml_templates/VAppTemplateReferences.xml +1 -0
  223. data/lib/ruby_vcloud_sdk/xml/xml_templates/VCloud.xml +1 -0
  224. data/lib/ruby_vcloud_sdk/xml/xml_templates/VMRecord.xml +1 -0
  225. data/lib/ruby_vcloud_sdk/xml/xml_templates/VMReference.xml +1 -0
  226. data/lib/ruby_vcloud_sdk/xml/xml_templates/VMReferences.xml +1 -0
  227. data/lib/ruby_vcloud_sdk/xml/xml_templates/VMWProviderVdcRecord.xml +1 -0
  228. data/lib/ruby_vcloud_sdk/xml/xml_templates/VMWProviderVdcReference.xml +1 -0
  229. data/lib/ruby_vcloud_sdk/xml/xml_templates/VMWProviderVdcReferences.xml +1 -0
  230. data/lib/ruby_vcloud_sdk/xml/xml_templates/Vdc.xml +1 -0
  231. data/lib/ruby_vcloud_sdk/xml/xml_templates/VdcReferences.xml +1 -0
  232. data/lib/ruby_vcloud_sdk/xml/xml_templates/VdcStorageProfile.xml +1 -0
  233. data/lib/ruby_vcloud_sdk/xml/xml_templates/VirtualCenterRecord.xml +1 -0
  234. data/lib/ruby_vcloud_sdk/xml/xml_templates/VirtualCenterReference.xml +1 -0
  235. data/lib/ruby_vcloud_sdk/xml/xml_templates/VirtualCenterReferences.xml +1 -0
  236. data/lib/ruby_vcloud_sdk/xml/xml_templates/Vm.xml +1 -0
  237. data/lib/ruby_vcloud_sdk/xml/xml_templates/VmPendingQuestion.xml +1 -0
  238. data/lib/ruby_vcloud_sdk/xml/xml_templates/VmQuestionAnswer.xml +1 -0
  239. data/lib/ruby_vcloud_sdk/xml/xml_templates/generate_dictionary.rb +8 -0
  240. data/spec/assets/admin_org_response.xml +75 -0
  241. data/spec/assets/catalog_add_item_response.xml +8 -0
  242. data/spec/assets/catalog_add_vapp_request.xml +5 -0
  243. data/spec/assets/catalog_item_added_response.xml +19 -0
  244. data/spec/assets/catalog_response.xml +19 -0
  245. data/spec/assets/existing_media_busy_response.xml +19 -0
  246. data/spec/assets/existing_media_catalog_item.xml +8 -0
  247. data/spec/assets/existing_media_delete_task_done.xml +6 -0
  248. data/spec/assets/existing_media_done_response.xml +11 -0
  249. data/spec/assets/existing_vapp_resolver_response.xml +3 -0
  250. data/spec/assets/existing_vapp_template_catalog_resolver_response.xml +3 -0
  251. data/spec/assets/existing_vapp_template_instantiate_response.xml +20 -0
  252. data/spec/assets/existing_vapp_template_instantiate_task_error_response.xml +7 -0
  253. data/spec/assets/existing_vapp_template_instantiate_task_start_response.xml +7 -0
  254. data/spec/assets/existing_vapp_template_instantiate_task_success_response.xml +7 -0
  255. data/spec/assets/existing_vapp_template_item_response.xml +8 -0
  256. data/spec/assets/existing_vapp_template_ready_response.xml +79 -0
  257. data/spec/assets/finalize_upload_task_done_response.xml +7 -0
  258. data/spec/assets/finalize_upload_task_response.xml +7 -0
  259. data/spec/assets/indy_disk_attach_request.xml +3 -0
  260. data/spec/assets/indy_disk_attach_task.xml +6 -0
  261. data/spec/assets/indy_disk_attach_task_error.xml +6 -0
  262. data/spec/assets/indy_disk_create_error.xml +1 -0
  263. data/spec/assets/indy_disk_create_request.xml +4 -0
  264. data/spec/assets/indy_disk_create_response.xml +19 -0
  265. data/spec/assets/indy_disk_delete_task.xml +6 -0
  266. data/spec/assets/indy_disk_detach_request.xml +3 -0
  267. data/spec/assets/indy_disk_detach_task.xml +6 -0
  268. data/spec/assets/indy_disk_response.xml +11 -0
  269. data/spec/assets/instantiated_suspended_vapp_response.xml +209 -0
  270. data/spec/assets/instantiated_vapp_delelete_done_task.xml +5 -0
  271. data/spec/assets/instantiated_vapp_delelete_running_task.xml +6 -0
  272. data/spec/assets/instantiated_vapp_network_config_add_network_request.xml +36 -0
  273. data/spec/assets/instantiated_vapp_network_config_modify_network_task_success.xml +6 -0
  274. data/spec/assets/instantiated_vapp_network_config_remove_network_request.xml +6 -0
  275. data/spec/assets/instantiated_vapp_network_config_section_response.xml +17 -0
  276. data/spec/assets/instantiated_vapp_off_response.xml +206 -0
  277. data/spec/assets/instantiated_vapp_on_response.xml +205 -0
  278. data/spec/assets/instantiated_vapp_power_task_running.xml +6 -0
  279. data/spec/assets/instantiated_vapp_power_task_success.xml +6 -0
  280. data/spec/assets/instantiated_vapp_response.xml +205 -0
  281. data/spec/assets/instantiated_vm_change_task_running.xml +6 -0
  282. data/spec/assets/instantiated_vm_change_task_success.xml +6 -0
  283. data/spec/assets/instantiated_vm_cpu_response.xml +11 -0
  284. data/spec/assets/instantiated_vm_insert_media_task_done.xml +6 -0
  285. data/spec/assets/instantiated_vm_memory_response.xml +11 -0
  286. data/spec/assets/instantiated_vm_modify_task_running.xml +6 -0
  287. data/spec/assets/instantiated_vm_modify_task_success.xml +5 -0
  288. data/spec/assets/instantiated_vm_network_section_response.xml +11 -0
  289. data/spec/assets/instantiated_vm_response.xml +149 -0
  290. data/spec/assets/media_add_to_catalog_request.xml +5 -0
  291. data/spec/assets/media_add_to_catalog_response.xml +8 -0
  292. data/spec/assets/media_delete_task_done.xml +6 -0
  293. data/spec/assets/media_upload_pending_response.xml +13 -0
  294. data/spec/assets/media_upload_request.xml +2 -0
  295. data/spec/assets/metadata_set_request.xml +3 -0
  296. data/spec/assets/metadata_set_task_done.xml +6 -0
  297. data/spec/assets/org_network_response.xml +22 -0
  298. data/spec/assets/reconfigure_vm_request.xml +133 -0
  299. data/spec/assets/reconfigure_vm_task.xml +8 -0
  300. data/spec/assets/session.xml +7 -0
  301. data/spec/assets/test-config.yml +38 -0
  302. data/spec/assets/undeploy_params.xml +1 -0
  303. data/spec/assets/vapp_template_catalog_resolver_response.xml +3 -0
  304. data/spec/assets/vapp_template_delelete_done_task.xml +5 -0
  305. data/spec/assets/vapp_template_delelete_running_task.xml +6 -0
  306. data/spec/assets/vapp_template_instantiate_request.xml +8 -0
  307. data/spec/assets/vapp_template_instantiate_with_locality_request.xml +14 -0
  308. data/spec/assets/vapp_template_no_disk_response.xml +27 -0
  309. data/spec/assets/vapp_template_ready_response.xml +79 -0
  310. data/spec/assets/vapp_template_upload_complete.xml +28 -0
  311. data/spec/assets/vapp_template_upload_failed.xml +28 -0
  312. data/spec/assets/vapp_template_upload_request.xml +4 -0
  313. data/spec/assets/vapp_template_upload_response.xml +25 -0
  314. data/spec/assets/vcloud_response.xml +56 -0
  315. data/spec/assets/vdc_response.xml +57 -0
  316. data/spec/spec_helper.rb +107 -0
  317. data/spec/unit/client_response.rb +700 -0
  318. data/spec/unit/client_spec.rb +1152 -0
  319. metadata +498 -0
data/README ADDED
@@ -0,0 +1 @@
1
+ Ruby VCloud SDK is a gem to simplify making vCloud Director API calls.
data/Rakefile ADDED
@@ -0,0 +1,50 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ $:.unshift(File.expand_path("../../rake", __FILE__))
4
+
5
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __FILE__)
6
+
7
+ require "rubygems"
8
+ require "bundler"
9
+ Bundler.setup(:default, :test)
10
+
11
+ require "rake"
12
+ begin
13
+ require "rspec/core/rake_task"
14
+ rescue LoadError
15
+ end
16
+
17
+ require "bundler_task"
18
+ require "ci_task"
19
+
20
+ gem_helper = Bundler::GemHelper.new(Dir.pwd)
21
+
22
+ desc "Build Ruby VCloud Client gem into the pkg directory"
23
+ task "build" do
24
+ gem_helper.build_gem
25
+ end
26
+
27
+ desc "Build and install Ruby VCloud Client into system gems"
28
+ task "install" do
29
+ Rake::Task["bundler:install"].invoke
30
+ gem_helper.install_gem
31
+ end
32
+
33
+ BundlerTask.new
34
+
35
+ if defined?(RSpec)
36
+ namespace :spec do
37
+ desc "Run Unit Tests"
38
+ rspec_task = RSpec::Core::RakeTask.new(:unit) do |t|
39
+ t.pattern = "spec/unit/**/*_spec.rb"
40
+ t.rspec_opts = %w(--format progress --colour)
41
+ end
42
+
43
+ CiTask.new do |task|
44
+ task.rspec_task = rspec_task
45
+ end
46
+ end
47
+
48
+ desc "Install dependencies and run tests"
49
+ task :spec => %w(bundler:install:test spec:unit)
50
+ end
@@ -0,0 +1,19 @@
1
+ $:.unshift(File.expand_path("..", __FILE__))
2
+
3
+ require "rubygems" # Needed for Ruby 1.8
4
+ require "logger"
5
+
6
+ module VCloudSdk; end
7
+
8
+ require "ruby_vcloud_sdk/xml/constants"
9
+ require "ruby_vcloud_sdk/xml/wrapper"
10
+ require "ruby_vcloud_sdk/xml/wrapper_classes"
11
+
12
+ require "ruby_vcloud_sdk/config"
13
+ require "ruby_vcloud_sdk/errors"
14
+ require "ruby_vcloud_sdk/util"
15
+ require "ruby_vcloud_sdk/client"
16
+ require "ruby_vcloud_sdk/ovf_directory"
17
+
18
+ require "ruby_vcloud_sdk/connection/connection"
19
+ require "ruby_vcloud_sdk/connection/file_uploader"
@@ -0,0 +1,899 @@
1
+ require "rest_client" # Need this for the exception classes
2
+ require "set"
3
+
4
+ module VCloudSdk
5
+
6
+ class Client
7
+ attr_reader :ovdc
8
+
9
+ def initialize(url, username, password, entities, control,
10
+ connection = nil)
11
+ @logger = Config.logger
12
+ @url = url
13
+ @organization = entities["organization"]
14
+ @ovdc_name = entities["virtual_datacenter"]
15
+ @vapp_catalog_name = entities["vapp_catalog"]
16
+ @media_catalog_name = entities["media_catalog"]
17
+ @control = control
18
+ @retries = @control["retries"]
19
+ @time_limit = @control["time_limit_sec"]
20
+ construct_rest_logger
21
+ Config.configure({ "rest_logger" => @rest_logger,
22
+ "rest_throttle" => control["rest_throttle"] })
23
+
24
+ if connection
25
+ @connection = connection
26
+ else
27
+ @connection = Connection::Connection.new(@url, @organization,
28
+ @time_limit["http_request"])
29
+ end
30
+ @root = @connection.connect(username, password)
31
+ @admin_root = @connection.get(@root.admin_root)
32
+ @entity_resolver_link = @root.entity_resolver.href
33
+ # We assume the organization does not change often so we can get it at
34
+ # login and cache it
35
+ @admin_org = @connection.get(@admin_root.organization(@organization))
36
+ @logger.info("Successfully connected.")
37
+ end
38
+
39
+ def get_catalog_vapp(id)
40
+ resolve_entity(id)
41
+ end
42
+
43
+ def get_vapp(obj)
44
+ if obj.is_a?(Xml::VApp)
45
+ obj
46
+ elsif obj.is_a?(String)
47
+ resolve_entity(obj)
48
+ else
49
+ raise CloudError, "Expecting Xml::VApp or String, got #{obj.inspect}."
50
+ end
51
+ end
52
+
53
+ def upload_vapp_template(vapp_name, directory)
54
+ ovdc = get_ovdc
55
+ @logger.info("Uploading VM #{vapp_name} to #{ovdc["name"]} in " +
56
+ "organization #{@organization}")
57
+ # if directory behaves like an OVFDirectory, then use it
58
+ is_ovf_directory = [:ovf_file, :ovf_file_path, :vmdk_file,
59
+ :vmdk_file_path].reduce(true) do |present, name|
60
+ present && directory.respond_to?(name)
61
+ end
62
+ ovf_directory = is_ovf_directory ? directory :
63
+ OVFDirectory.new(directory)
64
+ upload_params = Xml::WrapperFactory.create_instance(
65
+ "UploadVAppTemplateParams")
66
+ upload_params.name = vapp_name
67
+ vapp_template = @connection.post(ovdc.upload_link, upload_params)
68
+ catalog_name = @vapp_catalog_name
69
+ vapp_template = upload_vapp_files(vapp_template, ovf_directory)
70
+ raise ObjectNotFoundError, "Error uploading vApp template" unless
71
+ vapp_template
72
+ @logger.info("#{vapp_template.name} has tasks in progress. " +
73
+ "Waiting until done.")
74
+ vapp_template.running_tasks.each do |task|
75
+ monitor_task(task, @time_limit["process_descriptor_vapp_template"])
76
+ end
77
+ err_tasks = @connection.get(vapp_template).tasks.find_all {
78
+ |t| t.status != Xml::TASK_STATUS[:SUCCESS] }
79
+ unless err_tasks.empty?
80
+ @logger.error("Error uploading vApp template. " +
81
+ "Non-successful tasks:#{err_tasks}.")
82
+ raise CloudError, "Error uploading vApp template"
83
+ end
84
+ @logger.info("vApp #{vapp_name} uploaded, adding to " +
85
+ "catalog #{catalog_name}")
86
+ catalog_item = add_catalog_item(vapp_template, catalog_name)
87
+ @logger.info("vApp #{vapp_name} added to catalog " +
88
+ "#{catalog_name} #{catalog_item.to_s}")
89
+ catalog_item
90
+ rescue ApiError => e
91
+ log_exception(e, "Error in uploading vApp template #{vapp_name}")
92
+ rollback_upload_vapp(vapp_template)
93
+ raise e
94
+ end
95
+
96
+ def insert_catalog_media(vm, catalog_media_name)
97
+ catalog_media = get_catalog_media(catalog_media_name)
98
+ media = @connection.get(catalog_media.entity)
99
+ current_vm = @connection.get(vm)
100
+ insert_media(current_vm, media)
101
+ end
102
+
103
+ def eject_catalog_media(vm, catalog_media_name)
104
+ catalog_media = get_catalog_media(catalog_media_name)
105
+ unless catalog_media
106
+ raise CatalogMediaNotFoundError,
107
+ "Catalog media #{catalog_media_name} not found."
108
+ end
109
+ media = @connection.get(catalog_media.entity)
110
+ current_vm = @connection.get(vm)
111
+ eject_media(current_vm, media)
112
+ end
113
+
114
+ def upload_catalog_media(media_name, file, storage_profile = nil,
115
+ image_type = "iso")
116
+ ovdc = get_ovdc
117
+ @logger.info("Uploading media #{media_name} to #{storage_profile}/" +
118
+ "#{ovdc["name"]} in organization #{@organization}")
119
+ catalog_name = @media_catalog_name
120
+ upload_params = Xml::WrapperFactory.create_instance("Media")
121
+ upload_params.name = media_name
122
+ media_file = file.is_a?(String) ? File.new(file, "rb") : file
123
+ upload_params.size = media_file.stat.size
124
+ upload_params.image_type = image_type
125
+ upload_params.storage_profile = storage_profile
126
+ media = @connection.post(ovdc.upload_media_link, upload_params)
127
+ incomplete_file = media.incomplete_files.pop
128
+ @connection.put_file(incomplete_file.upload_link, media_file)
129
+ media = @connection.get(media)
130
+ add_catalog_item(media, catalog_name)
131
+ rescue ArgumentError, ApiError => e
132
+ log_exception(e, "Error uploading media #{media_name}" +
133
+ "to catalog #{catalog_name}. #{e.message}")
134
+ delete_media(media) if media
135
+ raise e
136
+ end
137
+
138
+ def delete_catalog_media(name)
139
+ raise ArgumentError, "Media name cannot be nil." unless name
140
+ catalog_media = get_catalog_media(name)
141
+ if catalog_media
142
+ media = @connection.get(catalog_media.entity)
143
+ delete_media(media)
144
+ @connection.delete(catalog_media)
145
+ end
146
+ rescue RestClient::ResourceNotFound => e
147
+ # Media might be deleted already
148
+ @logger.debug("Catalog media #{name} no longer exists.")
149
+ end
150
+
151
+ def delete_catalog_vapp(id)
152
+ raise ArgumentError, "Catalog ID cannot be nil." unless id
153
+ catalog_vapp = get_catalog_vapp(id)
154
+ if catalog_vapp
155
+ vapp = @connection.get(catalog_vapp.entity)
156
+ delete_vapp_template(vapp)
157
+ @connection.delete(catalog_vapp)
158
+ end
159
+ rescue => e
160
+ # vApp template might be deleted already
161
+ @logger.debug("Catalog vApp #{id} no longer exists.")
162
+ end
163
+
164
+ def delete_vapp(vapp)
165
+ @logger.info("Deleting vApp #{vapp.name}.")
166
+ current_vapp = @connection.get(vapp)
167
+ if is_vapp_status(current_vapp, :POWERED_ON)
168
+ raise CloudError,
169
+ "vApp #{vapp.name} is powered on, power-off before deleting."
170
+ end
171
+ delete_vapp_or_template(current_vapp, @retries["default"],
172
+ @time_limit["delete_vapp"], "vApp")
173
+ end
174
+
175
+ def instantiate_vapp_template(source_template_id, vapp_name,
176
+ description = nil, disk_locality = nil)
177
+ catalog_item = get_catalog_vapp(source_template_id)
178
+ unless catalog_item
179
+ @logger.error("Catalog item with ID #{source_template_id} not " +
180
+ "found in catalog #{@vapp_catalog_name}.")
181
+ raise ObjectNotFoundError, "Item with ID #{source_template_id} " +
182
+ "not found in catalog #{@vapp_catalog_name}."
183
+ end
184
+ src_vapp_template = @connection.get(catalog_item.entity)
185
+ instantiate_vapp_params = Xml::WrapperFactory.create_instance(
186
+ "InstantiateVAppTemplateParams")
187
+ instantiate_vapp_params.name = vapp_name
188
+ instantiate_vapp_params.description = description
189
+ instantiate_vapp_params.source = src_vapp_template
190
+ instantiate_vapp_params.all_eulas_accepted = true
191
+ instantiate_vapp_params.linked_clone = false
192
+ instantiate_vapp_params.set_locality = locality_spec(src_vapp_template,
193
+ disk_locality)
194
+ vdc = get_ovdc
195
+ vapp = @connection.post(vdc.instantiate_vapp_template_link,
196
+ instantiate_vapp_params)
197
+ vapp.running_tasks.each do |task|
198
+ begin
199
+ monitor_task(task, @time_limit["instantiate_vapp_template"])
200
+ rescue ApiError => e
201
+ log_exception(e, "Instantiate vApp template #{vapp_name} failed." +
202
+ " Task #{task.operation} did not complete successfully.")
203
+ delete_vapp(vapp)
204
+ raise e
205
+ end
206
+ end
207
+ @connection.get(vapp)
208
+ end
209
+
210
+ def reconfigure_vm(vm, &b)
211
+ b.call(vm)
212
+ monitor_task(@connection.post("#{vm.reconfigure_link.href}", vm,
213
+ Xml::MEDIA_TYPE[:VM]))
214
+ end
215
+
216
+ def get_metadata(entity, key)
217
+ metadata = @connection.get(generate_metadata_href(entity, key))
218
+ metadata.value
219
+ end
220
+
221
+ def set_metadata(entity, key, value)
222
+ metadata = Xml::WrapperFactory.create_instance("MetadataValue")
223
+ metadata.value = value
224
+ task = @connection.put(generate_metadata_href(entity, key), metadata,
225
+ Xml::MEDIA_TYPE[:METADATA_ITEM_VALUE])
226
+ monitor_task(task)
227
+ end
228
+
229
+ def delete_networks(vapp, exclude_nets = [])
230
+ current_vapp = get_vapp(vapp)
231
+ raise ObjectNotFoundError, "Cannot delete nets, vApp #{vapp.name} no " +
232
+ "longer exists" unless current_vapp
233
+ current = current_vapp.network_config_section.network_configs.map {
234
+ |n| n.network_name }
235
+ nets = current - exclude_nets
236
+ @logger.debug("nets:: current:#{current}, exclude:#{exclude_nets}, " +
237
+ "to delete:#{nets}")
238
+ return if nets.nil? || nets.length == 0
239
+ delete_network(current_vapp, *nets)
240
+ end
241
+
242
+ def add_network(vapp, network, vapp_net_name = nil,
243
+ fence_mode = Xml::FENCE_MODES[:BRIDGED])
244
+ current_network = @connection.get(network)
245
+ raise ObjectNotFoundError, "Cannot add network to vApp #{vapp.name}. " +
246
+ "The network #{network.name} no longer exists." unless current_network
247
+ current_vapp = get_vapp(vapp)
248
+ raise ObjectNotFoundError, "Cannot add network to vApp #{vapp.name}. " +
249
+ "The vApp #{vapp.name} no longer exists." unless current_vapp
250
+ network_config = Xml::WrapperFactory.create_instance("NetworkConfig")
251
+ new_vapp_net_name = vapp_net_name.nil? ?
252
+ current_network["name"] : vapp_net_name
253
+ copy_network_settings(current_network, network_config,
254
+ new_vapp_net_name, fence_mode)
255
+ current_vapp.network_config_section.add_network_config(network_config)
256
+ task = @connection.put(current_vapp.network_config_section,
257
+ current_vapp.network_config_section,
258
+ Xml::MEDIA_TYPE[:NETWORK_CONFIG_SECTION])
259
+ monitor_task(task)
260
+ end
261
+
262
+ # There must be no NICs on the network when it is deleted. Otherwise the
263
+ # task will fail. Use set_nic_network to move NICs onto other network or
264
+ # the NONE network prior to deleting the network from the vApp.
265
+ def delete_network(vapp, *network_names)
266
+ raise ArgumentError, "Must specify a network name to delete." if
267
+ network_names.nil? || network_names.length == 0
268
+ unique_network_names = network_names.uniq
269
+ @logger.info("Delete networks(s) #{unique_network_names.join(" ")} " +
270
+ "from vApp #{vapp.name}")
271
+ current_vapp = get_vapp(vapp)
272
+ unique_network_names.each do |n|
273
+ current_vapp.network_config_section.delete_network_config(n)
274
+ end
275
+ task = @connection.put(current_vapp.network_config_section,
276
+ current_vapp.network_config_section,
277
+ Xml::MEDIA_TYPE[:NETWORK_CONFIG_SECTION])
278
+ monitor_task(task)
279
+ end
280
+
281
+ # Size at creation is in bytes
282
+ # We currently assumes the disk is SCSI and bus sub type LSILOGIC
283
+ def create_disk(name, size_mb, vm = nil, retries = @retries["default"])
284
+ new_disk = Xml::WrapperFactory.create_instance("DiskCreateParams")
285
+ new_disk.name = name
286
+ new_disk.size_bytes = size_mb * 1024 * 1024 # VCD expects bytes
287
+ new_disk.bus_type = Xml::HARDWARE_TYPE[:SCSI_CONTROLLER]
288
+ new_disk.bus_sub_type = Xml::BUS_SUB_TYPE[:LSILOGIC]
289
+ new_disk.add_locality(vm) if vm
290
+ vdc = get_ovdc
291
+ @logger.info("Creating independent disk #{name} of #{size_mb}MB.")
292
+ @logger.info("Disk locality ist set to #{vm.name} #{vm.urn}.") if vm
293
+ disk = @connection.post(vdc.add_disk_link, new_disk,
294
+ Xml::MEDIA_TYPE[:DISK_CREATE_PARAMS])
295
+ raise ApiRequestError unless disk.respond_to?(:running_tasks)
296
+ # Creating a disk returns a disk with tasks inside
297
+ retries.times do |try|
298
+ return disk if disk.running_tasks.nil? || disk.running_tasks.empty?
299
+ @logger.info("Disk #{disk.urn} has running tasks. Waiting for " +
300
+ "tasks to finish. Try: #{try}/#{retries} ." )
301
+ disk.running_tasks.each do |t|
302
+ monitor_task(t)
303
+ end
304
+ disk = @connection.get(disk)
305
+ end
306
+ end
307
+
308
+ def delete_disk(disk)
309
+ current_disk = @connection.get(disk)
310
+ unless current_disk
311
+ @logger.warn("Disk #{disk.name} #{disk.urn} no longer exists.")
312
+ return
313
+ end
314
+ task = @connection.delete(current_disk.delete_link)
315
+ monitor_task(task) do |t|
316
+ @logger.info("Deleted disk #{current_disk.name} #{current_disk.urn}")
317
+ t
318
+ end
319
+ end
320
+
321
+ def attach_disk(disk, vm)
322
+ current_vm = @connection.get(vm)
323
+ raise ObjectNotFoundError, "VM #{vm.name} not found." unless current_vm
324
+
325
+ current_disk = @connection.get(disk)
326
+ unless current_disk
327
+ raise ObjectNotFoundError, "Disk #{disk.name} not found."
328
+ end
329
+
330
+ params = Xml::WrapperFactory.create_instance("DiskAttachOrDetachParams")
331
+ params.disk_href = current_disk.href
332
+ task = @connection.post(current_vm.attach_disk_link, params,
333
+ Xml::MEDIA_TYPE[:DISK_ATTACH_DETACH_PARAMS])
334
+ monitor_task(task) do |t|
335
+ @logger.info("Attached disk #{current_disk.name} to VM " +
336
+ "#{current_vm.name}.")
337
+ t
338
+ end
339
+ end
340
+
341
+ def detach_disk(disk, vm)
342
+ current_vm = @connection.get(vm)
343
+ raise ObjectNotFoundError, "VM #{vm.name} not found." unless current_vm
344
+
345
+ current_disk = @connection.get(disk)
346
+ unless current_disk
347
+ raise ObjectNotFoundError, "Disk #{disk.name} not found."
348
+ end
349
+
350
+ disk_href = current_disk.href
351
+
352
+ if is_vapp_status(current_vm, :SUSPENDED)
353
+ @logger.debug("vApp #{current_vm.name} suspended, discard state " +
354
+ "before detaching disk.")
355
+ raise VmSuspendedError, "discard state first"
356
+ end
357
+
358
+ begin
359
+ get_disk_id(current_vm, disk_href)
360
+ rescue DiskNotFoundError
361
+ @logger.warn("Disk #{current_disk.name} not found on VM " +
362
+ "#{current_vm.name}. No need to detach.")
363
+ return
364
+ end
365
+ params = Xml::WrapperFactory.create_instance("DiskAttachOrDetachParams")
366
+ params.disk_href = disk_href
367
+ task = @connection.post(current_vm.detach_disk_link, params,
368
+ Xml::MEDIA_TYPE[:DISK_ATTACH_DETACH_PARAMS])
369
+ monitor_task(task) do |t|
370
+ @logger.info("Detached disk #{current_disk.name} from VM " +
371
+ "#{current_vm.name}.")
372
+ t
373
+ end
374
+ end
375
+
376
+ def get_disk(disk_id)
377
+ resolve_entity(disk_id)
378
+ end
379
+
380
+ def power_on_vapp(vapp)
381
+ @logger.info("Powering on vApp #{vapp.name} .")
382
+ current_vapp = @connection.get(vapp)
383
+ unless current_vapp
384
+ raise ObjectNotFoundError, "vApp #{vapp.name} not found."
385
+ end
386
+ @logger.debug("vApp status: #{current_vapp["status"]}")
387
+ if is_vapp_status(current_vapp, :POWERED_ON)
388
+ @logger.info("vApp #{vapp.name} already powered-on.")
389
+ return
390
+ end
391
+ unless current_vapp.power_on_link
392
+ raise CloudError, "vApp #{vapp.name} not in a state to be " +
393
+ "powered on."
394
+ end
395
+ task = @connection.post(current_vapp.power_on_link, nil)
396
+ monitor_task(task, @time_limit["power_on"])
397
+ @logger.info("vApp #{current_vapp.name} powered on.")
398
+ task
399
+ end
400
+
401
+ def power_off_vapp(vapp, undeploy = true)
402
+ @logger.info("Powering off vApp #{vapp.name} .")
403
+ @logger.info("Undeploying vApp #{vapp.name} .") if undeploy
404
+ current_vapp = @connection.get(vapp)
405
+ unless current_vapp
406
+ raise ObjectNotFoundError, "vApp #{vapp.name} no longer exists."
407
+ end
408
+ @logger.debug("vApp status: #{current_vapp["status"]}")
409
+
410
+ if is_vapp_status(current_vapp, :SUSPENDED)
411
+ @logger.debug("vApp #{current_vapp.name} suspended, discard state " +
412
+ "before powering off.")
413
+ raise VappSuspendedError, "discard state first"
414
+ end
415
+
416
+ if undeploy
417
+ # Since we do not apparently differentiate between powered-off and
418
+ # undeployed in our status, we should check if the undeploy link is
419
+ # available first. If undeploy is not available and status is
420
+ # powered_off then it is undeployed.
421
+ unless current_vapp.undeploy_link
422
+ if is_vapp_status(current_vapp, :POWERED_OFF)
423
+ @logger.info("vApp #{vapp.name} already powered-off, undeployed.")
424
+ return
425
+ end
426
+ raise CloudError, "vApp #{vapp.name} not in a state be " +
427
+ "powered-off, undeployed."
428
+ end
429
+ params = Xml::WrapperFactory.create_instance("UndeployVAppParams")
430
+ task = @connection.post(current_vapp.undeploy_link, params)
431
+ monitor_task(task, @time_limit["undeploy"])
432
+ @logger.info("vApp #{current_vapp.name} powered-off, undeployed.")
433
+ task
434
+ else
435
+ unless current_vapp.power_off_link
436
+ if is_vapp_status(current_vapp, :POWERED_OFF)
437
+ @logger.info("vApp #{vapp.name} already powered off.")
438
+ return
439
+ end
440
+ raise CloudError, "vApp #{vapp.name} not in a state be powered off."
441
+ end
442
+ task = @connection.post(current_vapp.power_off_link, nil)
443
+ monitor_task(task, @time_limit["power_off"])
444
+ @logger.info("vApp #{current_vapp.name} powered off.")
445
+ task
446
+ end
447
+ end
448
+
449
+ def discard_suspended_state_vapp(vapp)
450
+ @logger.info("Discarding suspended state of vApp #{vapp.name}.")
451
+ current_vapp = @connection.get(vapp)
452
+ unless current_vapp
453
+ raise ObjectNotFoundError, "vApp #{vapp.name} no longer exists."
454
+ end
455
+ @logger.debug("vApp status: #{current_vapp["status"]}")
456
+
457
+ return unless is_vapp_status(current_vapp, :SUSPENDED)
458
+
459
+ @logger.info("Discarding suspended state of vApp #{current_vapp.name}.")
460
+ task = @connection.post(current_vapp.discard_state, nil)
461
+ monitor_task(task, @time_limit["undeploy"])
462
+ current_vapp = @connection.get(current_vapp)
463
+ @logger.info("vApp #{current_vapp.name} suspended state discarded.")
464
+ task
465
+ end
466
+
467
+ def reboot_vapp(vapp)
468
+ @logger.info("Rebooting vApp #{vapp.name}.")
469
+ current_vapp = @connection.get(vapp)
470
+ unless current_vapp
471
+ raise ObjectNotFoundError, "vApp #{vapp.name} no longer exists."
472
+ end
473
+ @logger.debug("vApp status: #{current_vapp["status"]}")
474
+
475
+ if is_vapp_status(current_vapp, :SUSPENDED)
476
+ @logger.debug("vApp #{current_vapp.name} suspended.")
477
+ raise VappSuspendedError, "vapp suspended"
478
+ end
479
+ if is_vapp_status(current_vapp, :POWERED_OFF)
480
+ @logger.debug("vApp #{current_vapp.name} powered off.")
481
+ raise VappPoweredOffError, "vapp powered off"
482
+ end
483
+
484
+ @logger.info("Rebooting vApp #{current_vapp.name}.")
485
+ task = @connection.post(current_vapp.reboot_link, nil)
486
+ monitor_task(task)
487
+ current_vapp = @connection.get(current_vapp)
488
+ @logger.info("vApp #{current_vapp.name} rebooted.")
489
+ task
490
+ end
491
+
492
+ def get_ovdc
493
+ vdc = @admin_org.vdc(@ovdc_name)
494
+ raise ObjectNotFoundError, "VDC #{@ovdc_name} not found." unless vdc
495
+ @connection.get(vdc)
496
+ end
497
+
498
+ def get_catalog(name)
499
+ catalog = @connection.get(@admin_org.catalog(name))
500
+ end
501
+
502
+ private
503
+
504
+ ERROR_STATUSES = [Xml::TASK_STATUS[:ABORTED], Xml::TASK_STATUS[:ERROR],
505
+ Xml::TASK_STATUS[:CANCELED]]
506
+ SUCCESS_STATUS = [Xml::TASK_STATUS[:SUCCESS]]
507
+
508
+ def resolve_entity(id)
509
+ url = "#{@entity_resolver_link}#{id}"
510
+ entity = @connection.get(url)
511
+ raise ObjectNotFoundError, "Unable to get entity" unless entity
512
+ @connection.get(entity.link)
513
+ end
514
+
515
+ def get_disk_id(vm, disk_href)
516
+ hardware_section = vm.hardware_section
517
+ disk = hardware_section.hard_disks.find do |d|
518
+ d.host_resource["disk"] == disk_href
519
+ end
520
+ unless disk
521
+ raise DiskNotFoundError, "Disk with href #{disk_href} not attached " +
522
+ "to VM #{vm.name}."
523
+ end
524
+ disk.disk_id
525
+ end
526
+
527
+ def log_exception(e, message = nil)
528
+ @logger.error(message) if message
529
+ @logger.error(e.message)
530
+ @logger.error(e.backtrace.join("\n\r"))
531
+ end
532
+
533
+ def copy_network_settings(network, network_config, vapp_net_name,
534
+ fence_mode)
535
+ config_ip_scope = network_config.ip_scope
536
+ net_ip_scope = network.ip_scope
537
+ config_ip_scope.is_inherited = net_ip_scope.is_inherited?
538
+ config_ip_scope.gateway= net_ip_scope.gateway
539
+ config_ip_scope.netmask = net_ip_scope.netmask
540
+ if net_ip_scope.start_address
541
+ config_ip_scope.start_address = net_ip_scope.start_address
542
+ end
543
+ if net_ip_scope.end_address
544
+ config_ip_scope.end_address = net_ip_scope.end_address
545
+ end
546
+ network_config.fence_mode = fence_mode
547
+ network_config.parent_network["name"] = network["name"]
548
+ network_config.parent_network["href"] = network["href"]
549
+ network_config["networkName"] = vapp_net_name
550
+ end
551
+
552
+ def delete_vapp_template(vapp_template)
553
+ delete_vapp_or_template(vapp_template, @retries["default"],
554
+ @time_limit["delete_vapp_template"], "vApp Template")
555
+ end
556
+
557
+ def check_vapp_for_remove_link(vapp)
558
+ current_vapp = @connection.get(vapp)
559
+ unless current_vapp.remove_link
560
+ raise ObjectNotFoundError, "No link available to delete vApp."
561
+ end
562
+ return current_vapp
563
+ end
564
+
565
+ def delete_vapp_or_template(vapp, retries, time_limit, type_name)
566
+ retries.times do |try|
567
+ @logger.info("Deleting #{type_name} #{vapp.name}")
568
+ current_vapp = @connection.get(vapp)
569
+ if (current_vapp.running_tasks.empty?)
570
+ Util.retry_operation(current_vapp, @retries["default"],
571
+ @control["backoff"]) do
572
+ current_vapp = check_vapp_for_remove_link(current_vapp)
573
+ end
574
+ Util.retry_operation(current_vapp.remove_link, @retries["default"],
575
+ @control["backoff"]) do
576
+ monitor_task(@connection.delete(current_vapp.remove_link),
577
+ time_limit) do |task|
578
+ @logger.info("#{type_name} #{current_vapp.name} deleted.")
579
+ return task
580
+ end
581
+ end
582
+ else
583
+ @logger.info("#{vapp.name} has tasks in progress, wait until done.")
584
+ current_vapp.running_tasks.each do |task|
585
+ monitor_task(task)
586
+ end
587
+ sleep (@control["backoff"] ** try)
588
+ end
589
+ end
590
+ raise ApiRequestError,
591
+ "Unable to delete #{type_name} after #{retries} attempts"
592
+ end
593
+
594
+ def insert_media(vm, media, retries = @retries["default"])
595
+ params = Xml::WrapperFactory.create_instance("MediaInsertOrEjectParams")
596
+ params.media_href = media.href
597
+
598
+ # Wait for media to be ready
599
+ retries.times do |try|
600
+ @logger.info("Inserting media #{media.name} into VM #{vm.name}.")
601
+ current_media = @connection.get(media)
602
+ if (current_media.running_tasks.empty?)
603
+ Util.retry_operation(vm.insert_media_link, @retries["default"],
604
+ @control["backoff"]) do
605
+ task = @connection.post(vm.insert_media_link, params,
606
+ Xml::MEDIA_TYPE[:MEDIA_INSERT_EJECT_PARAMS])
607
+ monitor_task(task) do |t|
608
+ raise CloudError, "Error inserting media #{media.name} " +
609
+ "into VM #{vm.name}." if t.status != "success"
610
+ @logger.info("Inserted media #{media.name} into VM #{vm.name}.")
611
+ return t
612
+ end
613
+ end
614
+ else
615
+ @logger.info("#{current_media.name} has tasks in progress, " +
616
+ "waiting until done.")
617
+ current_media.running_tasks.each do |task|
618
+ monitor_task(task)
619
+ end
620
+ sleep (@control["backoff"] ** try)
621
+ end
622
+ end
623
+ raise ApiRequestError, "Unable to insert media #{media.name} into " +
624
+ "VM #{vm.name} after #{retries} attempts"
625
+ end
626
+
627
+ def eject_media(vm, media, retries = @retries["default"])
628
+ params = Xml::WrapperFactory.create_instance("MediaInsertOrEjectParams")
629
+ params.media_href = media.href
630
+
631
+ #Wait for media to be ready
632
+ retries.times do |try|
633
+ @logger.info("Ejecting media #{media.name} from VM #{vm.name}.")
634
+ current_media = @connection.get(media)
635
+ if (current_media.running_tasks.empty?)
636
+ return eject_media_task(vm, params, media)
637
+ else
638
+ @logger.info("#{current_media.name} has tasks in progress, " +
639
+ "waiting until done.")
640
+ current_media.running_tasks.each do |task|
641
+ monitor_task(task)
642
+ end
643
+ sleep (@control["backoff"] ** try)
644
+ end
645
+ end
646
+ raise ApiRequestError, "Unable to eject media #{media.name} from " +
647
+ "VM #{vm.name} after #{retries} attempts"
648
+ end
649
+
650
+ def delete_media(media, retries = @retries["default"],
651
+ time_limit = @time_limit["delete_media"])
652
+ retries.times do |try|
653
+ @logger.info("Deleting media #{media.name}")
654
+ current_media = @connection.get(media)
655
+ if (current_media.running_tasks.empty?)
656
+ Util.retry_operation(current_media.delete_link, @retries["default"],
657
+ @control["backoff"]) do
658
+ monitor_task(@connection.delete(current_media.delete_link),
659
+ time_limit) do |task|
660
+ @logger.info("Media #{current_media.name} deleted.")
661
+ return task
662
+ end
663
+ end
664
+ else
665
+ @logger.info("#{current_media.name} has tasks in progress, " +
666
+ "waiting until done.")
667
+ current_media.running_tasks.each do |task|
668
+ monitor_task(task)
669
+ end
670
+ sleep (@control["backoff"] ** try)
671
+ end
672
+ end
673
+ raise ApiRequestError, "Unable to delete #{type_name} after "
674
+ "#{retries} attempts"
675
+ end
676
+
677
+ def get_catalog_media(name)
678
+ get_catalog_item(name, Xml::MEDIA_TYPE[:MEDIA], @media_catalog_name)
679
+ end
680
+
681
+ # Get catalog item from catalog by name and type.
682
+ # Raises an exception if catalog is not found.
683
+ # Returns nil if an item matching the name and type is not found.
684
+ # Otherwise, returns the catalog item.
685
+ # The catalog item is not the uderlying object itself, i.e. vApp template.
686
+ def get_catalog_item(name, item_type, catalog_name)
687
+ raise ObjectNotFoundError, "Catalog item name cannot be nil" unless name
688
+ unless @admin_org.catalog(catalog_name)
689
+ raise ObjectNotFoundError, "Catalog #{catalog_name} not found."
690
+ end
691
+ # For some reason, if the catalog no longer exists,
692
+ # VCD throws a Forbidden exception when getting
693
+ catalog = @connection.get(@admin_org.catalog(catalog_name))
694
+ items = catalog.catalog_items(name)
695
+ if items.nil? || items.empty?
696
+ @logger.debug("Item #{name} does not exist in catalog #{catalog_name}")
697
+ return nil
698
+ end
699
+ items.each do |i|
700
+ entity = @connection.get(i)
701
+ # Return the entity node. Another get on that node is necessary to
702
+ # get the actual object itself
703
+ return entity if entity.entity["type"] == item_type
704
+ end
705
+ nil
706
+ end
707
+
708
+ def get_vm_network_connections(vm)
709
+ current_vm = @connection.get(vm)
710
+ unless current_vm
711
+ raise ObjectNotFoundError, "VM #{vm.name} no longer exists."
712
+ end
713
+ @connection.get(current_vm.network_connection_section)
714
+ end
715
+
716
+ def task_progressed?(current_task, prev_progress, prev_status)
717
+ (current_task.progress && (current_task.progress != prev_progress)) ||
718
+ (current_task.status && (current_task.status != prev_status))
719
+ end
720
+
721
+ def task_is_success(current_task, success = SUCCESS_STATUS)
722
+ success.map { |s| s.downcase }.find {
723
+ |s| s == current_task.status.downcase }
724
+ end
725
+
726
+ def task_has_error(current_task, error_statuses = ERROR_STATUSES)
727
+ error_statuses.map { |s| s.downcase }.find {
728
+ |s| s == current_task.status.downcase }
729
+ end
730
+
731
+ def monitor_task(task, time_limit = @time_limit["default"],
732
+ error_statuses = ERROR_STATUSES, success = SUCCESS_STATUS,
733
+ delay = @control["delay"], &b)
734
+ iterations = time_limit / delay
735
+ i = 0
736
+ prev_progress = task.progress
737
+ prev_status = task.status
738
+ current_task = task
739
+ while (i < iterations)
740
+ @logger.debug("#{current_task.urn} #{current_task.operation} is " +
741
+ "#{current_task.status}")
742
+ if task_is_success(current_task, success)
743
+ if b
744
+ return b.call(current_task)
745
+ else
746
+ return current_task
747
+ end
748
+ elsif task_has_error(current_task, error_statuses)
749
+ raise ApiRequestError, "Task #{task.urn} #{task.operation} did " +
750
+ "not complete successfully."
751
+ elsif task_progressed?(current_task, prev_progress, prev_status)
752
+ @logger.debug("task status #{prev_status} => " +
753
+ "#{current_task.status}, progress #{prev_progress}%" +
754
+ " => #{current_task.progress}%, timer #{i} reset.")
755
+ prev_progress = current_task.progress
756
+ prev_status = current_task.status
757
+ i = 0 #reset clock if status changes or running task makes progress
758
+ sleep(delay)
759
+ else
760
+ @logger.debug("Approximately #{i * delay}s elapsed waiting for " +
761
+ "#{current_task.operation} to reach " +
762
+ "#{success.join("/")}/#{error_statuses.join("/")}." +
763
+ " Checking again in #{delay} seconds.")
764
+ @logger.debug("Task #{task.urn} progress: " +
765
+ "#{current_task.progress} %.") if current_task.progress
766
+ sleep(delay)
767
+ end
768
+ current_task = @connection.get(task)
769
+ i += 1
770
+ end
771
+ raise ApiTimeoutError, "Task #{task.operation} did not complete " +
772
+ "within limit of #{time_limit} seconds."
773
+ end
774
+
775
+
776
+ # TODO use times.upload_vapp_files
777
+ def upload_vapp_files(vapp, ovf_directory,
778
+ tries = @retries["upload_vapp_files"], try = 0)
779
+ current_vapp = @connection.get(vapp)
780
+ return current_vapp if !current_vapp.files || current_vapp.files.empty?
781
+
782
+ @logger.debug("vapp files left to upload #{current_vapp.files}.")
783
+ @logger.debug("vapp incomplete files left to upload " +
784
+ "#{current_vapp.incomplete_files}.")
785
+ raise ApiTimeoutError, "Unable to finish uploading vApp after " +
786
+ "#{tries} tries #{current_vapp.files}." if tries == try
787
+
788
+ current_vapp.incomplete_files.each do |f|
789
+ # switch on extension
790
+ case f.name.split(".").pop.downcase
791
+ when "ovf"
792
+ @logger.info("Uploading OVF file: " +
793
+ "#{ovf_directory.ovf_file_path} for #{vapp.name}")
794
+ @connection.put(f.upload_link, ovf_directory.ovf_file.read,
795
+ Xml::MEDIA_TYPE[:OVF])
796
+ when "vmdk"
797
+ @logger.info("Uploading VMDK file " +
798
+ "#{ovf_directory.vmdk_file_path(f.name)} for #{vapp.name}")
799
+ @connection.put_file(f.upload_link,
800
+ ovf_directory.vmdk_file(f.name))
801
+ end
802
+ end
803
+ #repeat
804
+ sleep (2 ** try)
805
+ upload_vapp_files(current_vapp, ovf_directory, tries, try + 1)
806
+ end
807
+
808
+ def add_catalog_item(item, catalog_name)
809
+ unless @admin_org.catalog(catalog_name)
810
+ raise ArgumentError,
811
+ "Error adding #{item.name}, catalog #{catalog_name} not found."
812
+ end
813
+ catalog = @connection.get(@admin_org.catalog(catalog_name))
814
+ raise ObjectNotFoundError, "Error adding #{item.name}, catalog " +
815
+ "#{catalog_name} not available." unless catalog
816
+ catalog_item = Xml::WrapperFactory.create_instance("CatalogItem")
817
+ catalog_item.name = item.name
818
+ catalog_item.entity = item
819
+ @logger.info("Adding #{catalog_item.name} to catalog #{catalog_name}")
820
+ @connection.post(catalog.add_item_link, catalog_item,
821
+ Xml::ADMIN_MEDIA_TYPE[:CATALOG_ITEM])
822
+ end
823
+
824
+ def generate_metadata_href(entity, key)
825
+ raise ObjectNotFoundError, "Entity #{entity.name} does not expose a " +
826
+ "metadata link method." if !entity.respond_to?(:metadata_link)
827
+ "#{entity.metadata_link.href}/#{key}"
828
+ end
829
+
830
+ def get_vapp_by_name(name)
831
+ @logger.debug("Getting vApp #{name}")
832
+ vdc = get_ovdc
833
+ node = vdc.get_vapp(name)
834
+ raise ObjectNotFoundError, "vApp #{name} does not exist." unless node
835
+ vapp = @connection.get(node)
836
+ raise ObjectNotFoundError, "vApp #{name} does not exist." unless vapp
837
+ vapp
838
+ end
839
+
840
+ def locality_spec(src_vapp_template, disk_locality)
841
+ disk_locality ||= []
842
+ locality = {}
843
+ disk_locality.each do |disk|
844
+ current_disk = @connection.get(disk)
845
+ unless current_disk
846
+ @logger.warn("Disk #{disk.name} no longer exists.")
847
+ next
848
+ end
849
+ src_vapp_template.vms.each do |vm|
850
+ locality[vm] = current_disk
851
+ end
852
+ end
853
+ locality
854
+ end
855
+
856
+ def is_vapp_status(current_vapp, status)
857
+ current_vapp["status"] == Xml::RESOURCE_ENTITY_STATUS[status].to_s
858
+ end
859
+
860
+ def rollback_upload_vapp(vapp_template)
861
+ @logger.error("Rolling back changes.")
862
+ begin
863
+ delete_vapp_template(vapp_template) if vapp_template
864
+ rescue => rollbackex
865
+ log_exception(rollbackex, "Error in rolling back failed vApp " +
866
+ "template #{vapp_name}.")
867
+ end
868
+ end
869
+
870
+ def eject_media_task(vm, params, media)
871
+ Util.retry_operation(vm.eject_media_link, @retries["default"],
872
+ @control["backoff"]) do
873
+ task = @connection.post(vm.eject_media_link, params,
874
+ Xml::MEDIA_TYPE[:MEDIA_INSERT_EJECT_PARAMS])
875
+ monitor_task(task) do |t|
876
+ if t.status != "success"
877
+ raise CloudError, "Error ejecting media #{media.name} from " +
878
+ "VM #{vm.name}."
879
+ end
880
+ @logger.info("Ejected media #{media.name} from VM #{vm.name}.")
881
+ return t
882
+ end
883
+ end
884
+ end
885
+
886
+ def construct_rest_logger
887
+ @logger.debug("constructing rest_logger")
888
+ rest_log_filename = File.join(File.dirname(@logger.instance_eval {
889
+ @logdev }.dev.path), "rest")
890
+ log_file = File.open(rest_log_filename, "w")
891
+ log_file.sync = true
892
+
893
+ @rest_logger = Logger.new(log_file || STDOUT)
894
+ @rest_logger.level = @logger.level
895
+ @rest_logger.formatter = @logger.formatter
896
+ end
897
+ end
898
+
899
+ end