def _upload_image_to_glance( self, context, src_file_name, image_id, instance): vm_task_state = instance.task_state file_size = os.path.getsize(src_file_name) read_file_handle = fileutils.file_open(src_file_name, "rb") metadata = IMAGE_API.get(context, image_id) # The properties and other fields that we need to set for the image. image_metadata = {"disk_format": "qcow2", "is_public": "false", "name": metadata['name'], "status": "active", "container_format": "bare", "size": file_size, "properties": {"owner_id": instance['project_id']}} util.start_transfer(context, read_file_handle, file_size, image_id=metadata['id'], image_meta=image_metadata, task_state=task_states.IMAGE_UPLOADING, instance=instance) self._update_vm_task_state(instance, task_state=vm_task_state)
def _upload_image_to_glance(self, context, src_file_name, image_id, instance): vm_task_state = instance.task_state file_size = os.path.getsize(src_file_name) read_file_handle = fileutils.file_open(src_file_name, "rb") metadata = IMAGE_API.get(context, image_id) # The properties and other fields that we need to set for the image. image_metadata = { "disk_format": "qcow2", "is_public": "false", "name": metadata['name'], "status": "active", "container_format": "bare", "size": file_size, "properties": { "owner_id": instance['project_id'] } } util.start_transfer(context, read_file_handle, file_size, image_id=metadata['id'], image_meta=image_metadata, task_state=task_states.IMAGE_UPLOADING, instance=instance) self._update_vm_task_state(instance, task_state=vm_task_state)
def _do_snapshot_2(self, context, instance, image_id, update_task_state): # a) get provider node id provider_node_id = self._get_provider_node_id(instance) provider_nodes = self.compute_adapter.list_nodes(ex_node_ids=[provider_node_id]) if not provider_nodes: LOG.error('instance %s is not found' % instance.uuid) raise exception.InstanceNotFound(instance_id=instance.uuid) if len(provider_nodes)>1: LOG.error('instance %s are more than one' % instance.uuid) raise exception_ex.MultiInstanceConfusion provider_node = provider_nodes[0] # b) export-instance to s3 # self.compute_adapter.ex_stop_node(provider_node) try: task = self.compute_adapter.create_export_instance_task(provider_node_id, CONF.provider_opts.storage_tmp_dir) except: task = self.compute_adapter.create_export_instance_task(provider_node_id, CONF.provider_opts.storage_tmp_dir) while not task.is_completed(): time.sleep(10) task = self.compute_adapter.get_task_info(task) obj_key = task.export_to_s3_info.s3_key obj_bucket = task.export_to_s3_info.s3_bucket # c) download from s3 obj = self.storage_adapter.get_object(obj_bucket,obj_key) conv_dir = '%s/%s' % (CONF.provider_opts.conversion_dir,image_id) fileutils.ensure_tree(conv_dir) org_full_name = '%s/%s.vmdk' % (conv_dir,image_id) self.storage_adapter.download_object(obj,org_full_name) # d) convert to qcow2 dest_full_name = '%s/%s.qcow2' % (conv_dir,image_id) convert_image(org_full_name, dest_full_name, 'qcow2') # upload to glance update_task_state(task_state=task_states.IMAGE_UPLOADING, expected_state=task_states.IMAGE_PENDING_UPLOAD) file_size = os.path.getsize(dest_full_name) metadata = self.glance_api.get(context, image_id) image_metadata = {"disk_format": "qcow2", "is_public": "false", "name": metadata['name'], "status": "active", "container_format": "bare", "size": file_size, "properties": {"owner_id": instance['project_id']}} src_file_handle = fileutils.file_open(dest_full_name, "rb") self.glance_api.create(context,image_metadata,src_file_handle) src_file_handle.close()
def _download_vmdk_from_vcloud(self, context, src_url, dst_file_name): # local_file_handle = open(dst_file_name, "wb") local_file_handle = fileutils.file_open(dst_file_name, "wb") remote_file_handle = urllib2.urlopen(src_url) file_size = remote_file_handle.headers['content-length'] util.start_transfer(context, remote_file_handle, file_size, write_file_handle=local_file_handle)
def _do_snapshot_1(self, context, instance, image_id, update_task_state): # 1) get provider node provider_node_id = self._get_provider_node_id(instance) provider_nodes = self.compute_adapter.list_nodes(ex_node_ids=[provider_node_id]) if not provider_nodes: LOG.error('instance %s is not found' % instance.uuid) raise exception.InstanceNotFound if len(provider_nodes)>1: LOG.error('instance %s are more than one' % instance.uuid) raise exception_ex.MultiInstanceConfusion provider_node = provider_nodes[0] # 2) get root-volume id provider_volumes = self.compute_adapter.list_volumes(node=provider_node) if not provider_volumes: raise exception.VolumeNotFound provider_volume = provider_volumes[0] # 3) export self.compute_adapter.export_volume(provider_volume.id, CONF.provider_opts.conversion_dir, image_id, cgw_host_id=CONF.provider_opts.cgw_host_id, cgw_host_ip=CONF.provider_opts.cgw_host_ip, cgw_username=CONF.provider_opts.cgw_username, cgw_certificate=CONF.provider_opts.cgw_certificate, transfer_station=CONF.provider_opts.storage_tmp_dir) # 4) upload to glance src_file_name = '%s/%s' %(CONF.provider_opts.conversion_dir, image_id) file_size = os.path.getsize(src_file_name) metadata = self.glance_api.get(context, image_id) image_metadata = {"disk_format": "qcow2", "is_public": "false", "name": metadata['name'], "status": "active", "container_format": "bare", "size": file_size, "properties": {"owner_id": instance['project_id']}} src_file_handle = fileutils.file_open(src_file_name, "rb") self.glance_api.create(context,image_metadata,src_file_handle) src_file_handle.close()
def spawn(self, context, instance, image_meta, injected_files, admin_password, network_info=None, block_device_info=None): #import pdb # pdb.set_trace() LOG.debug('[vcloud nova driver] spawn: %s' % instance.uuid) mac_address = '' if len(network_info) > 0: mac_address = network_info[0]['address'] name = instance['name'] state = power_state.BUILDING # 0.get vorg, user name,password vdc from configuration file (only one # org) node_name = instance.node vorg_name = self._session.org user_name = self._session.username password = self._session.password vdc_name = self._session.vdc vcloud_host = self._session.host_ip # 1.1 get image id, vm info ,flavor info # image_uuid = instance.image_ref if 'id' in image_meta: # create from image image_uuid = image_meta['id'] else: # create from volume image_uuid = image_meta['properties']['image_id'] vm_uuid = instance.uuid vm_name = instance.name vm_hostname = instance.hostname #vm_flavor_id = instance.get_flavor().flavorid vm_flavor_name = instance.get_flavor().name vcloud_flavor_id = CONF.vcloud.vcloud_flavor_map[vm_flavor_name] vm_task_state = instance.task_state # 1.3 (optional) is_poweron = True # 2~3 get vmdk file. check if the image or volume vmdk file cached first image_cache_dir = CONF.vcloud.vcloud_conversion_dir volume_cache_dir = CONF.vcloud.vcloud_volumes_dir this_conversion_dir = '%s/%s' % (CONF.vcloud.vcloud_conversion_dir, vm_uuid) fileutils.ensure_tree(this_conversion_dir) os.chdir(this_conversion_dir) converted_file_name = this_conversion_dir + \ '/converted-file.vmdk' block_device_mapping = driver.block_device_info_get_mapping( block_device_info) image_vmdk_file_name = '%s/%s.vmdk' % ( image_cache_dir, image_uuid) volume_file_name = '' if len(block_device_mapping) > 0: volume_id = block_device_mapping[0][ 'connection_info']['data']['volume_id'] volume_file_name = '%s/%s.vmdk' % ( volume_cache_dir, volume_id) # 2.1 check if the image or volume vmdk file cached if os.path.exists(volume_file_name): # if volume cached, move the volume file to conversion dir shutil.move(volume_file_name, converted_file_name) elif os.path.exists(image_vmdk_file_name): # if image cached, copy ghe image file to conversion dir shutil.copy2(image_vmdk_file_name, converted_file_name) else: # if NOT cached, download qcow2 file from glance to local, then convert it to vmdk # tmp_dir = '/hctemp' self._update_vm_task_state( instance, task_state=vcloud_task_states.DOWNLOADING) metadata = IMAGE_API.get(context, image_uuid) file_size = int(metadata['size']) read_iter = IMAGE_API.download(context, image_uuid) glance_file_handle = util.GlanceFileRead(read_iter) orig_file_name = this_conversion_dir + \ '/' + image_uuid + '.tmp' orig_file_handle = fileutils.file_open(orig_file_name, "wb") util.start_transfer(context, glance_file_handle, file_size, write_file_handle=orig_file_handle, task_state=vcloud_task_states.DOWNLOADING, instance=instance) # 2.2. convert to vmdk self._update_vm_task_state( instance, task_state=vcloud_task_states.CONVERTING) if metadata["disk_format"] == 'qcow2': convert_commond = "qemu-img convert -f %s -O %s %s %s" % \ ('qcow2', 'vmdk', orig_file_name, converted_file_name) convert_result = subprocess.call([convert_commond], shell=True) if convert_result != 0: LOG.error('convert qcow2 to vmdk failed') # do something, change metadata # file_size = os.path.getsize(converted_file_name) elif metadata["disk_format"] == 'raw': convert_commond = "qemu-img convert -f %s -O %s %s %s" % \ ('raw', 'vmdk', orig_file_name, converted_file_name) convert_result = subprocess.call([convert_commond], shell=True) if convert_result != 0: LOG.error('convert qcow2 to vmdk failed') # do something, change metadata # file_size = os.path.getsize(converted_file_name) else: os.rename(orig_file_name, converted_file_name) shutil.copy2(converted_file_name,image_vmdk_file_name) # 3. vmdk to ovf self._update_vm_task_state( instance, task_state=vcloud_task_states.PACKING) vmx_file_dir = '%s/%s' % (CONF.vcloud.vcloud_conversion_dir,'vmx') vmx_name = 'base-%s.vmx' % vcloud_flavor_id vmx_cache_full_name = '%s/%s' % (vmx_file_dir, vmx_name) vmx_full_name = '%s/%s' % (this_conversion_dir, vmx_name) shutil.copy2(vmx_cache_full_name, vmx_full_name) ovf_name = '%s/%s.ovf' % (this_conversion_dir,vm_uuid) mk_ovf_cmd = "ovftool -o %s %s" % (vmx_full_name, ovf_name) mk_ovf_result = subprocess.call(mk_ovf_cmd, shell=True) if mk_ovf_result != 0: LOG.error('make ovf faild!') self._update_vm_task_state(instance, task_state=vm_task_state) return # add mac address to ovf if mac_address != '': self._add_mac_address_to_ovf(ovf_name, mac_address) # 5~6: UPLOAD ovf to vcloud and create a vm # todo:5. upload ovf to vcloud template, using image's uuid as template name # todo:6. create vm from template self._update_vm_task_state( instance, task_state=vcloud_task_states.NETWORK_CREATING) self.create_networks(network_info) net_name = None for vif in network_info: net_name = vif['id'] self.plug_vifs(instance, network_info) self._update_vm_task_state( instance, task_state=vcloud_task_states.IMPORTING) vapp_name = self._get_vcloud_vapp_name(instance) if not net_name: if is_poweron: create_vapp_cmd = 'ovftool --powerOn' \ ' %s "vcloud://%s:%s@%s?org=%s&vdc=%s&vapp=%s"' % \ (ovf_name, user_name, password, vcloud_host, vorg_name, vdc_name, vapp_name) else: create_vapp_cmd = 'ovftool %s "vcloud://%s:%s@%s?org=%s&vdc=%s&vapp=%s"' % \ (ovf_name, user_name, password, vcloud_host, vorg_name, vdc_name, vapp_name) else: if is_poweron: create_vapp_cmd = 'ovftool --powerOn --net:"VM Network=%s"' \ ' %s "vcloud://%s:%s@%s?org=%s&vdc=%s&vapp=%s"' % \ (net_name, ovf_name, user_name, password, vcloud_host, vorg_name, vdc_name, vapp_name) else: create_vapp_cmd = 'ovftool --net:"VM Network=%s" %s "vcloud://%s:%s@%s?org=%s&vdc=%s&vapp=%s"' % \ (net_name, ovf_name, user_name, password, vcloud_host, vorg_name, vdc_name, vapp_name) fileutils.delete_if_exists( '%s/%s.mf' % (this_conversion_dir, vm_uuid)) create_vapp_cmd_result = subprocess.call(create_vapp_cmd, shell=True) if create_vapp_cmd_result != 0: LOG.error('create vapp faild!') self._update_vm_task_state(instance, task_state=vm_task_state) return self._update_vm_task_state( instance, task_state=vcloud_task_states.VM_CREATING) # import pdb # pdb.set_trace() if is_poweron: expected_vapp_status = VCLOUD_STATUS.POWERED_ON else: expected_vapp_status = VCLOUD_STATUS.POWERED_OFF vapp_name = self._get_vcloud_vapp_name(instance) vapp_status = self._get_vcloud_vapp_status(vapp_name) LOG.debug('vapp status: %s' % vapp_status) retry_times = 60 while vapp_status != expected_vapp_status and retry_times > 0: time.sleep(3) vapp_status = self._get_vcloud_vapp_status(vapp_name) LOG.debug('vapp status: %s' % vapp_status) retry_times = retry_times - 1 # 7. clean up self._update_vm_task_state(instance, task_state=vm_task_state) shutil.rmtree(this_conversion_dir, ignore_errors=True)
def _do_snapshot_2(self, context, instance, image_id, update_task_state): # xxx(wangfeng) # import pdb # pdb.set_trace() # a) get provider node id provider_node_id = self._get_provider_node_id(instance) provider_nodes = self.compute_adapter.list_nodes(ex_node_ids=[provider_node_id]) if not provider_nodes: LOG.error('instance %s is not found' % instance.uuid) raise exception.InstanceNotFound if len(provider_nodes)>1: LOG.error('instance %s are more than one' % instance.uuid) raise exception_ex.MultiInstanceConfusion provider_node = provider_nodes[0] # b) export-instance to s3 # self.compute_adapter.ex_stop_node(provider_node) try: task = self.compute_adapter.create_export_instance_task(provider_node_id, CONF.provider_opts.storage_tmp_dir) except: task = self.compute_adapter.create_export_instance_task(provider_node_id, CONF.provider_opts.storage_tmp_dir) while not task.is_completed(): time.sleep(10) task = self.compute_adapter.get_task_info(task) obj_key = task.export_to_s3_info.s3_key obj_bucket = task.export_to_s3_info.s3_bucket # c) download from s3 obj = self.storage_adapter.get_object(obj_bucket,obj_key) conv_dir = '%s/%s' % (CONF.provider_opts.conversion_dir,image_id) fileutils.ensure_tree(conv_dir) org_full_name = '%s/%s.vmdk' % (conv_dir,image_id) # with open(org_full_name, 'wb') as f: # for chunk in self.storage_adapter.download_object_as_stream(obj,chunk_size=CHUNK_SIZE): # if chunk: # f.write(chunk) # f.flush() self.storage_adapter.download_object(obj,org_full_name) # d) convert to qcow2 dest_full_name = '%s/%s.qcow2' % (conv_dir,image_id) convert_image(org_full_name, dest_full_name, 'qcow2') # upload to glance update_task_state(task_state=task_states.IMAGE_UPLOADING, expected_state=task_states.IMAGE_PENDING_UPLOAD) file_size = os.path.getsize(dest_full_name) metadata = self.glance_api.get(context, image_id) image_metadata = {"disk_format": "qcow2", "is_public": "false", "name": metadata['name'], "status": "active", "container_format": "bare", "size": file_size, "properties": {"owner_id": instance['project_id']}} src_file_handle = fileutils.file_open(dest_full_name, "rb") self.glance_api.create(context,image_metadata,src_file_handle) src_file_handle.close()
def spawn(self, context, instance, image_meta, injected_files, admin_password, network_info=None, block_device_info=None): #import pdb #pdb.set_trace() LOG.debug('[vcloud nova driver] spawn: %s' % instance.uuid) mac_address = '' if len(network_info) > 0: mac_address = network_info[0]['address'] name = instance['name'] state = power_state.BUILDING # 0.get vorg, user name,password vdc from configuration file (only one # org) node_name = instance.node vorg_name = self._session.org user_name = self._session.username password = self._session.password vdc_name = self._session.vdc vcloud_host = self._session.host_ip # 1.1 get image id, vm info ,flavor info # image_uuid = instance.image_ref if 'id' in image_meta: # create from image image_uuid = image_meta['id'] else: # create from volume image_uuid = image_meta['properties']['image_id'] vm_uuid = instance.uuid vm_name = instance.name vm_hostname = instance.hostname #vm_flavor_id = instance.get_flavor().flavorid vm_flavor_name = instance.get_flavor().name vcloud_flavor_id = CONF.vcloud.vcloud_flavor_map[vm_flavor_name] vm_task_state = instance.task_state # 1.3 (optional) is_poweron = True # 2~3 get vmdk file. if boot from volume ,check if the vmdk file exist os.chdir(CONF.vcloud.vcloud_conversion_dir) converted_file_name = CONF.vcloud.vcloud_conversion_dir + \ '/converted-file.vmdk' image_vmdk_file_name = '%s/%s.vmdk' % ( CONF.vcloud.vcloud_conversion_dir, image_uuid) orig_file_name = CONF.vcloud.vcloud_conversion_dir + \ '/' + image_uuid + '.tmp' block_device_mapping = driver.block_device_info_get_mapping( block_device_info) volume_file_name = '' if len(block_device_mapping) > 0: volume_id = block_device_mapping[0]['connection_info']['data'][ 'volume_id'] volume_file_name = '%s/%s.vmdk' % (CONF.vcloud.vcloud_volumes_dir, volume_id) if os.path.exists(volume_file_name): shutil.move(volume_file_name, converted_file_name) elif os.path.exists(image_vmdk_file_name): os.rename(image_vmdk_file_name, converted_file_name) else: # 2. download qcow2 file from glance to local # tmp_dir = '/hctemp' self._update_vm_task_state( instance, task_state=vcloud_task_states.DOWNLOADING) metadata = IMAGE_API.get(context, image_uuid) file_size = int(metadata['size']) read_iter = IMAGE_API.download(context, image_uuid) glance_file_handle = util.GlanceFileRead(read_iter) orig_file_name = CONF.vcloud.vcloud_conversion_dir + \ '/' + image_uuid + '.tmp' orig_file_handle = fileutils.file_open(orig_file_name, "wb") util.start_transfer(context, glance_file_handle, file_size, write_file_handle=orig_file_handle, task_state=vcloud_task_states.DOWNLOADING, instance=instance) # 3. convert to vmdk self._update_vm_task_state( instance, task_state=vcloud_task_states.CONVERTING) if metadata["disk_format"] == 'qcow2': convert_commond = "qemu-img convert -f %s -O %s %s %s" % \ ('qcow2', 'vmdk', orig_file_name, converted_file_name) convert_result = subprocess.call([convert_commond], shell=True) if convert_result != 0: LOG.error('convert qcow2 to vmdk failed') # do something, change metadata # file_size = os.path.getsize(converted_file_name) elif metadata["disk_format"] == 'raw': convert_commond = "qemu-img convert -f %s -O %s %s %s" % \ ('raw', 'vmdk', orig_file_name, converted_file_name) convert_result = subprocess.call([convert_commond], shell=True) if convert_result != 0: LOG.error('convert qcow2 to vmdk failed') # do something, change metadata # file_size = os.path.getsize(converted_file_name) else: os.rename(orig_file_name, converted_file_name) # 4. vmdk to ovf self._update_vm_task_state(instance, task_state=vcloud_task_states.PACKING) ovf_name = '%s/%s.ovf' % (CONF.vcloud.vcloud_conversion_dir, vm_uuid) vmx_name = '%s/base-%s.vmx' % (CONF.vcloud.vcloud_conversion_dir, vcloud_flavor_id) mk_ovf_cmd = "ovftool -o %s %s" % (vmx_name, ovf_name) mk_ovf_result = subprocess.call(mk_ovf_cmd, shell=True) if mk_ovf_result != 0: LOG.error('make ovf faild!') self._update_vm_task_state(instance, task_state=vm_task_state) return # add mac address to ovf if mac_address != '': self._add_mac_address_to_ovf(ovf_name, mac_address) # 5~6: UPLOAD ovf to vcloud and create a vm #todo:5. upload ovf to vcloud template, using image's uuid as template name #todo:6. create vm from template self._update_vm_task_state( instance, task_state=vcloud_task_states.NETWORK_CREATING) self.create_networks(network_info) for vif in network_info: net_name = vif['id'] self.plug_vifs(instance, network_info) self._update_vm_task_state(instance, task_state=vcloud_task_states.IMPORTING) vapp_name = self._get_vcloud_vapp_name(instance) if not net_name: if is_poweron: create_vapp_cmd = 'ovftool --powerOn' \ ' %s "vcloud://%s:%s@%s?org=%s&vdc=%s&vapp=%s"' % \ (ovf_name, user_name, password, vcloud_host, vorg_name, vdc_name, vapp_name) else: create_vapp_cmd = 'ovftool %s "vcloud://%s:%s@%s?org=%s&vdc=%s&vapp=%s"' % \ (ovf_name, user_name, password, vcloud_host, vorg_name, vdc_name, vapp_name) else: if is_poweron: create_vapp_cmd = 'ovftool --powerOn --net:"VM Network=%s"' \ ' %s "vcloud://%s:%s@%s?org=%s&vdc=%s&vapp=%s"' % \ (net_name, ovf_name, user_name, password, vcloud_host, vorg_name, vdc_name, vapp_name) else: create_vapp_cmd = 'ovftool --net:"VM Network=%s" %s "vcloud://%s:%s@%s?org=%s&vdc=%s&vapp=%s"' % \ (net_name, ovf_name, user_name, password, vcloud_host, vorg_name, vdc_name, vapp_name) fileutils.delete_if_exists( '%s/%s.mf' % (CONF.vcloud.vcloud_conversion_dir, vm_uuid)) create_vapp_cmd_result = subprocess.call(create_vapp_cmd, shell=True) if create_vapp_cmd_result != 0: LOG.error('create vapp faild!') self._update_vm_task_state(instance, task_state=vm_task_state) return self._update_vm_task_state(instance, task_state=vcloud_task_states.VM_CREATING) # import pdb # pdb.set_trace() if is_poweron: expected_vapp_status = VCLOUD_STATUS.POWERED_ON else: expected_vapp_status = VCLOUD_STATUS.POWERED_OFF vapp_name = self._get_vcloud_vapp_name(instance) vapp_status = self._get_vcloud_vapp_status(vapp_name) LOG.debug('vapp status: %s' % vapp_status) retry_times = 60 while vapp_status != expected_vapp_status and retry_times > 0: time.sleep(3) vapp_status = self._get_vcloud_vapp_status(vapp_name) LOG.debug('vapp status: %s' % vapp_status) retry_times = retry_times - 1 # 7. clean self._update_vm_task_state(instance, task_state=vm_task_state) os.chdir(CONF.vcloud.vcloud_conversion_dir) fileutils.delete_if_exists(orig_file_name) fileutils.delete_if_exists(ovf_name) fileutils.delete_if_exists(vm_uuid + '-disk1.vmdk') os.rename(converted_file_name, image_vmdk_file_name)