class SignedOvaImport(SampleBase): """ Demonstrates the workflow to import an OVA file into the content library, as an OVF library item. Note: the workflow needs an existing VC DS with available storage. """ #SIGNED_OVA_FILENAME = 'nostalgia-signed.ova' # SIGNED_OVA_FILENAME = 'IoTC_VA-2.0.2.12565-32613116_OVF10.ova' # SIGNED_OVA_RELATIVE_DIR = '../resources/signedOvaWithCertWarning/' def __init__(self): SampleBase.__init__(self, self.__doc__) self.servicemanager = None self.client = None self.helper = None self.datastore_name = None #self.lib_name = 'Pulse_Content_sb' self.local_lib_id = None self.lib_item_name = None self.lib_item_id = None def _options(self): self.argparser.add_argument('-datastorename', '--datastorename', required=True, help='The name of the datastore.') self.argparser.add_argument( '-libitemname', '--libitemname', required=True, help='The name of the Library Item Inside Content Library.') self.argparser.add_argument( '-locallibid', '--locallibid', required=True, help='The ID of Local Library to which the OVA has to be linked.') self.argparser.add_argument('-ovaname', '--ovaname', required=True, help='Name of the OVA.') self.argparser.add_argument('-ovapath', '--ovapath', required=True, help='Path to the OVA.') def _setup(self): self.servicemanager = self.get_service_manager() self.client = ClsApiClient(self.servicemanager) self.helper = ClsApiHelper(self.client, self.skip_verification) def _execute(self): # Build the storage backing for the library to be created using given datastore name self.datastore_name = self.args.datastorename storage_backings = self.helper.create_storage_backings( service_manager=self.servicemanager, datastore_name=self.datastore_name) #Assigning Library Item Name self.lib_item_name = self.args.libitemname # Create a local content library backed by the VC datastore using vAPIs #self.local_lib_id = self.helper.create_local_library(storage_backings, self.lib_name) self.local_lib_id = self.args.locallibid # Create a new library item in the content library for uploading the files self.lib_item_id = self.helper.create_library_item( library_id=self.local_lib_id, item_name=self.lib_item_name, item_description='Pulse OVA', item_type='ovf') print('Library item created. ID: {0}'.format(self.lib_item_id)) #Assigning OVA name and Path self.SIGNED_OVA_FILENAME = self.args.ovaname self.SIGNED_OVA_RELATIVE_DIR = self.args.ovapath ova_file_map = self.helper.get_ova_file_map( self.SIGNED_OVA_RELATIVE_DIR, local_filename=self.SIGNED_OVA_FILENAME) # Create a new upload session for uploading the files # To ignore expected warnings and skip preview info check, # you can set create_spec.warning_behavior during session creation session_id = self.client.upload_service.create( create_spec=UpdateSessionModel(library_item_id=self.lib_item_id), client_token=generate_random_uuid()) self.helper.upload_files_in_session(ova_file_map, session_id) # Wait for terminal preview state and obtain preview warnings if any #self.wait_for_terminal_preview_state(session_id, AVAILABLE) self.wait_for_terminal_preview_state(session_id, AVAILABLE) session = self.client.upload_service.get(session_id) preview_info = session.preview_info # Collect generated preview warning types preview_warning_types = [] print('Preview warnings for the session are the following:') for preview_warning in preview_info.warnings: print(preview_warning.message.default_message) preview_warning_types.append(preview_warning.type) # Ignore preview warnings on session ignore_warning_behaviors = [] for warning_type in preview_warning_types: warning_behavior = WarningBehavior(type=warning_type, ignored=True) ignore_warning_behaviors.append(warning_behavior) self.client.upload_service.update( session_id, update_spec=UpdateSessionModel( warning_behavior=ignore_warning_behaviors)) print( 'All preview warnings are ignored, proceeding to complete the session' ) self.client.upload_service.complete(session_id) self.client.upload_service.delete(session_id) print( 'Uploaded ova file as an ovf template to library item {0}'.format( self.lib_item_id)) def wait_for_terminal_preview_state(self, session_id, expected_terminal_preview_state, timeout_sec=300): """ Periodically checks update session for preview state to reach a terminal state. :param session_id: ID of update session for which preview state is checked :param expected_terminal_preview_state: expected terminal preview state :param timeout_sec: number of seconds to wait before timing out """ preview_state = None start_time = time.time() terminal_preview_state_list = [NOT_APPLICABLE, AVAILABLE] while (time.time() - start_time) < timeout_sec: session = self.client.upload_service.get(session_id) if session.state == 'ERROR': raise Exception( 'Session is in error state, error message: {}'.format( session.error_message)) preview_state = session.preview_info.state # check if preview state is in one of the terminal states if preview_state not in terminal_preview_state_list: time.sleep(1) else: break if preview_state != expected_terminal_preview_state: raise Exception( 'Preview state did not reach expected {} state, actual preview state: ' '{}'.format(expected_terminal_preview_state, preview_state)) def _cleanup(self): if self.local_lib_id: self.client.local_library_service.delete( library_id=self.local_lib_id) print('Deleted library ID: {0}'.format(self.local_lib_id))
class ContentUpdate(SampleBase): """ Demonstrates the workflow of updating a content library item. Note: the workflow needs an existing datastore (of type vmfs) with available storage. """ ISO_FILE_1 = 'test.iso' ISO_FILE_2 = 'test-2.iso' ISO_ITEM_NAME = 'test' def __init__(self): SampleBase.__init__(self, self.__doc__) self.servicemanager = None self.client = None self.helper = None self.datastore_name = None self.lib_name = "demo-lib" self.local_library = None def _options(self): self.argparser.add_argument('-datastorename', '--datastorename', help='The name of the datastore where ' 'the library will be created.') def _setup(self): self.datastore_name = self.args.datastorename assert self.datastore_name is not None self.servicemanager = self.get_service_manager() self.client = ClsApiClient(self.servicemanager) self.helper = ClsApiHelper(self.client, self.skip_verification) def _execute(self): storage_backings = self.helper.create_storage_backings( self.servicemanager, self.datastore_name) library_id = self.helper.create_local_library(storage_backings, self.lib_name) self.local_library = self.client.local_library_service.get(library_id) self.delete_and_upload_scenario(library_id) self.replace_scenario(library_id) def replace_scenario(self, library_id): """ :param library_id: the Iso item will be created, and then replaced in this library :return: None Content update scenario 2: Update ISO library item by creating an update session for the item, then adding the new ISO file using the same session file name into the update session, which will replace the existing ISO file upon session complete. """ iso_item_id = self.helper.create_library_item( library_id=library_id, item_name=self.ISO_ITEM_NAME, item_description='Sample iso file', item_type='iso') print('ISO Library item version (on creation) {0}:'.format( self.get_item_version(iso_item_id))) iso_files_map = self.helper.get_iso_file_map( item_filename=self.ISO_FILE_1, disk_filename=self.ISO_FILE_1) self.helper.upload_files(library_item_id=iso_item_id, files_map=iso_files_map) original_version = self.get_item_version(iso_item_id) print('ISO Library item version (on original content upload) {0}:'. format(original_version)) session_id = self.client.upload_service.create( create_spec=UpdateSessionModel(library_item_id=iso_item_id), client_token=generate_random_uuid()) # Use the same item filename (update endpoint, as it's a replace scenario) iso_files_map = self.helper.get_iso_file_map( item_filename=self.ISO_FILE_1, disk_filename=self.ISO_FILE_2) self.helper.upload_files_in_session(iso_files_map, session_id) self.client.upload_service.complete(session_id) self.client.upload_service.delete(session_id) updated_version = self.get_item_version(iso_item_id) print('ISO Library item version (after content update): {0}'.format( updated_version)) assert updated_version > original_version, 'content update should increase the version' def delete_and_upload_scenario(self, library_id): """ :param library_id: the OVF item will be created and updated in this library :return: None Content update scenario 1: Update OVF library item by creating an update session for the OVF item, removing all existing files in the session, then adding all new files into the same update session, and completing the session to finish the content update. """ # Create a new library item in the content library for uploading the files ovf_item_id = self.helper.create_library_item( library_id=library_id, item_name='demo-ovf-item', item_description='Sample simple VM template', item_type='ovf') assert ovf_item_id is not None print('Library item created id: {0}'.format(ovf_item_id)) print('OVF Library item version (at creation) {0}:'.format( self.get_item_version(ovf_item_id))) # Upload a VM template to the CL ovf_files_map = self.helper.get_ovf_files_map( ClsApiHelper.SIMPLE_OVF_RELATIVE_DIR) self.helper.upload_files(library_item_id=ovf_item_id, files_map=ovf_files_map) print('Uploaded ovf and vmdk files to library item {0}'.format( ovf_item_id)) original_version = self.get_item_version(ovf_item_id) print('OVF Library item version (on original content upload): {0}'. format(original_version)) # Create a new session and perform content update session_id = self.client.upload_service.create( create_spec=UpdateSessionModel(library_item_id=ovf_item_id), client_token=generate_random_uuid()) existing_files = self.client.upload_file_service.list(session_id) for file in existing_files: print('deleting {0}'.format(file.name)) self.client.upload_file_service.remove(session_id, file.name) ovf_files_map = self.helper.get_ovf_files_map( ovf_location=ClsApiHelper.PLAIN_OVF_RELATIVE_DIR) self.helper.upload_files_in_session(ovf_files_map, session_id) self.client.upload_service.complete(session_id) self.client.upload_service.delete(session_id) updated_version = self.get_item_version(ovf_item_id) print('OVF Library item version (after content update): {0}'.format( updated_version)) assert updated_version > original_version, 'content update should increase the version' def get_item_version(self, item_id): ovf_item_model = self.client.library_item_service.get(item_id) pre_update_version = ovf_item_model.content_version return pre_update_version def _cleanup(self): if self.local_library: self.client.local_library_service.delete( library_id=self.local_library.id) print('Deleted Library Id: {0}'.format(self.local_library.id))