PRL_RESULT Task_GetBackupTreeSource::run_body()
{
	//https://bugzilla.sw.ru/show_bug.cgi?id=267152
	CAuthHelperImpersonateWrapper _impersonate( &getClient()->getAuthHelper() );

	PRL_RESULT nRetCode = PRL_ERR_SUCCESS;
	QFileInfoList excludeList;
	QFileInfoList dirList;
	QFileInfoList fileList;

	if (PRL_FAILED(nRetCode = connect()))
		goto exit;

	if (PRL_FAILED(nRetCode = GetBackupTreeRequest(m_sUuid, m_sBackupTree)))
		goto exit;


exit:
	setLastErrorCode(nRetCode);
	return nRetCode;
}
PRL_RESULT CDspHaClusterHelper::moveToClusterResource(const QString & sName, const QString & sRemoteNode)
{
	QProcess proc;
	QStringList args;
	args += SHAMAN_CMD_TO;
	args += getResourcePrefix() + sName;
	args += sRemoteNode;

	PRL_RESULT res = runHaman(args, proc);
	if (PRL_FAILED(res))
		WRITE_TRACE(DBG_FATAL, "cluster resource '%s' removing error", QSTR2UTF8(sName));
	return res;
}
PRL_RESULT Task_MigrateCtSource::migrateStoppedCt()
{
	PRL_RESULT nRetCode = PRL_ERR_SUCCESS;
	int i;
	QList<QPair<QFileInfo, QString> > dList;
	QList<QPair<QFileInfo, QString> > fList;

	if ( !(m_nReservedFlags & PVM_DONT_COPY_VM) )
		/* get full directories and files lists for migration */
		if ((nRetCode = GetEntryLists(m_sVmHomePath, dList, fList)) != PRL_ERR_SUCCESS)
			return nRetCode;

	if (PRL_FAILED(nRetCode = SendStartRequest()))
		return nRetCode;

	/* calculate total transaction size */
	for (i = 0; i < fList.size(); ++i)
		m_nTotalSize += fList.at(i).first.size();

	m_pSender = SmartPtr<CVmFileListCopySender>(new CVmFileListCopySenderClient(m_pIoClient));
	m_pVmCopySource = SmartPtr<CVmFileListCopySource>(
			new CVmFileListCopySource(
				m_pSender.getImpl(),
				m_pVmConfig->getVmIdentification()->getVmUuid(),
				m_sVmHomePath,
				m_nTotalSize,
				getLastError(),
				m_nTimeout));
	m_pVmCopySource->SetRequest(getRequestPackage());
	m_pVmCopySource->SetVmDirectoryUuid(m_sVzDirUuid);
	m_pVmCopySource->SetProgressNotifySender(NotifyClientsWithProgress);

	nRetCode = m_pVmCopySource->Copy(dList, fList);
	if (PRL_FAILED(nRetCode))
		WRITE_TRACE(DBG_FATAL, "Error occurred while migration with code [%#x][%s]",
			nRetCode, PRL_RESULT_TO_STRING(nRetCode));

	return nRetCode;
}
PRL_RESULT CDspHaClusterHelper::removeClusterResource(const QString & sName, bool removeFromAllNodes)
{
	QProcess proc;
	QStringList args;
	args += removeFromAllNodes ? SHAMAN_CMD_DEL_EVERYWHERE : SHAMAN_CMD_DEL;
	args += getResourcePrefix() + sName;

	WRITE_TRACE(DBG_FATAL, "%s removing resource %s", removeFromAllNodes ? "recursively" : "", QSTR2UTF8(sName));

	PRL_RESULT res = runHaman(args, proc);
	if (PRL_FAILED(res))
		WRITE_TRACE(DBG_FATAL, "cluster resource '%s' removing error", QSTR2UTF8(sName));
	return res;
}
PRL_RESULT CDspHaClusterHelper::updateClusterResourceParams(const QString & sName,
		CVmHighAvailability *oldHa, CVmHighAvailability *newHa, const QString & newPath, PRL_VM_TYPE vmType)
{
	QProcess proc;
	QStringList args;
	QString cmd;

	PRL_ASSERT(oldHa);
	PRL_ASSERT(newHa);

	if (newHa->isEnabled() != oldHa->isEnabled())
		cmd = newHa->isEnabled() ? SHAMAN_CMD_ADD : SHAMAN_CMD_DEL;
	else if (newHa->getPriority() != oldHa->getPriority()) {
		cmd = SHAMAN_CMD_SET;
	} else {
		/* HA options are not changed */
		return PRL_ERR_SUCCESS;
	}

	/*
	 * Don't run shaman if HA is disabled in VM config and the command line
	 * doesn't contain '--ha-enable yes'.
	 */
	if ((newHa->isEnabled() == oldHa->isEnabled()) && !newHa->isEnabled())
		return PRL_ERR_SUCCESS;

	args += cmd;
	args += getResourcePrefix(vmType) + sName;

	if (cmd != SHAMAN_CMD_DEL) {
		/*
		 * Specify all parameters from the config when doing 'shaman add'.
		 * This is needed e.g. when registering an already existing VM - newly
		 * created cluster resource for this VM should contain all actual
		 * HA parameter values.
		 */
		if ((newHa->getPriority() != oldHa->getPriority()) || (cmd == SHAMAN_CMD_ADD)) {
			args += QString("--path");
			args += newPath;
			args += QString("--prio");
			args += QString("%1").arg(newHa->getPriority());
		}
	}

	PRL_RESULT res = runHaman(args, proc);
	if (PRL_FAILED(res))
		WRITE_TRACE(DBG_FATAL, "cluster resource '%s' registration error", QSTR2UTF8(sName));
	return res;
}
PRL_RESULT Task_VzManager::umount_env()
{
	CProtoCommandPtr cmd = CProtoSerializer::ParseCommand( getRequestPackage());
	if ( ! cmd->IsValid() )
		return PRL_ERR_FAILURE;

	PRL_RESULT res;
	QString sUuid = cmd->GetVmUuid();

	res = check_env_state(PVE::DspCmdVmUmount, sUuid);
	if (PRL_FAILED(res))
		return res;

	return get_op_helper()->umount_env(sUuid);
}
PRL_RESULT Task_VzManager::checkAndLockRegisterParameters(
			CVmDirectory::TemporaryCatalogueItem *pVmInfo)
{
	PRL_RESULT lockResult = CDspService::instance()->getVmDirManager()
			.checkAndLockNotExistsExclusiveVmParameters(QStringList(), pVmInfo);

	if (PRL_FAILED( lockResult))
	{
		switch (lockResult)
		{
		case PRL_ERR_VM_ALREADY_REGISTERED_VM_UUID:
			getLastError()->addEventParameter(
				new CVmEventParameter( PVE::String, pVmInfo->vmUuid, EVT_PARAM_RETURN_PARAM_TOKEN));
			break;

		case PRL_ERR_VM_ALREADY_REGISTERED_VM_PATH:
			getLastError()->addEventParameter(
				new CVmEventParameter( PVE::String, pVmInfo->vmName, EVT_PARAM_MESSAGE_PARAM_0));
			getLastError()->addEventParameter(
				new CVmEventParameter( PVE::String, pVmInfo->vmXmlPath, EVT_PARAM_MESSAGE_PARAM_1));
			break;

		case PRL_ERR_VM_ALREADY_REGISTERED_VM_NAME:
			getLastError()->addEventParameter(
				new CVmEventParameter( PVE::String, pVmInfo->vmName, EVT_PARAM_MESSAGE_PARAM_0));
			break;

		case PRL_ERR_VM_ALREADY_REGISTERED:
			getLastError()->addEventParameter(
					new CVmEventParameter( PVE::String, pVmInfo->vmName, EVT_PARAM_MESSAGE_PARAM_0));
			break;

		case PRL_ERR_VM_ALREADY_REGISTERED_UNIQUE_PARAMS:; // use default

		default:
			getLastError()->addEventParameter(
				 new CVmEventParameter( PVE::String, pVmInfo->vmUuid, EVT_PARAM_RETURN_PARAM_TOKEN));
			getLastError()->addEventParameter(
				 new CVmEventParameter( PVE::String, pVmInfo->vmXmlPath, EVT_PARAM_RETURN_PARAM_TOKEN));
			getLastError()->addEventParameter(
				 new CVmEventParameter( PVE::String, pVmInfo->vmName, EVT_PARAM_RETURN_PARAM_TOKEN));
		}

		return lockResult;
	}

	return PRL_ERR_SUCCESS;
}
PRL_RESULT CDspHaClusterHelper::renameClusterResource(const QString & oldName,
		CVmHighAvailability *oldHa, const QString & newName, const QString & newPath)
{
	PRL_ASSERT(oldHa);

	if (!oldHa->isEnabled())
		return PRL_ERR_SUCCESS;

	PRL_RESULT res = addClusterResource(newName, oldHa, newPath);
	if (PRL_FAILED(res))
		return res;

	/* Ignore errors on remove, can't do anything with them. */
	removeClusterResource(oldName);

	return PRL_ERR_SUCCESS;
}
PRL_RESULT Task_MigrateCtTarget::migrateStoppedVm()
{
	PRL_RESULT nRetCode = PRL_ERR_SUCCESS;
	CDispToDispCommandPtr pReply;
	SmartPtr<IOPackage> pPackage;

	m_pSender = SmartPtr<CVmFileListCopySender>(new CVmFileListCopySenderServer(
			CDspService::instance()->getIOServer(),
			m_pStartDispConnection->GetConnectionHandle()));

	/* CVmFileListCopyTarget will use Vm uuid in progress messages for clients, so will use original Vm uuid */
	m_pVmMigrateTarget = SmartPtr<CVmFileListCopyTarget>(
		new CVmFileListCopyTarget(m_pSender.getImpl(), m_sOriginVmUuid, m_sTargetVmHomePath, NULL, m_nTimeout));


	// Connect to handle traffic report package
	bool bConnected = QObject::connect(
		m_pStartDispConnection.getImpl(),
		SIGNAL(onPackageReceived(IOSender::Handle, const SmartPtr<IOPackage>)),
		SLOT(handlePackage(IOSender::Handle, const SmartPtr<IOPackage>)),
		Qt::DirectConnection );
	PRL_ASSERT(bConnected);

	// set empty string for default path
	pReply = CDispToDispProtoSerializer::CreateVmMigrateReply(QString());
	pPackage = DispatcherPackage::createInstance(
		pReply->GetCommandId(), pReply->GetCommand()->toString(), m_pStartPackage);
	m_pStartDispConnection->sendPackage(pPackage);

	nRetCode = QThread::exec();

	QObject::disconnect(
		m_pStartDispConnection.getImpl(),
		SIGNAL(onPackageReceived(IOSender::Handle, const SmartPtr<IOPackage>)),
		this,
		SLOT(handlePackage(IOSender::Handle, const SmartPtr<IOPackage>)));

	if (PRL_FAILED(nRetCode))
		return nRetCode;

	return PRL_ERR_SUCCESS;
}
PRL_RESULT Task_VzManager::setupFirewall(SmartPtr<CVmConfiguration> &pConfig)
{
	CFirewallHelper fw(pConfig);

	PRL_RESULT ret = fw.Execute();
	if (PRL_FAILED(ret))
	{
		if ( ret == PRL_ERR_FIREWALL_TOOL_EXECUTED_WITH_ERROR )
		{
			getLastError()->setEventType( PET_DSP_EVT_ERROR_MESSAGE );
			getLastError()->addEventParameter(
					new CVmEventParameter( PVE::String,
						fw.GetErrorMessage(),
						EVT_PARAM_DETAIL_DESCRIPTION )
					);
		}
		return ret;
	}
	return PRL_ERR_SUCCESS;
}
PRL_RESULT Task_VzManager::resume_env()
{
	CProtoCommandPtr pCmd = CProtoSerializer::ParseCommand( getRequestPackage() );
	if (!pCmd->IsValid())
		return PRL_ERR_UNRECOGNIZED_REQUEST;

	PRL_RESULT res;
	QString sUuid = pCmd->GetVmUuid();

	res = check_env_state(PVE::DspCmdVmResume, sUuid);
	if (PRL_FAILED(res))
		return res;

	SmartPtr<CVmConfiguration> pConfig = getVzHelper()->getCtConfig(getClient(), sUuid);
	if (!pConfig)
		return PRL_ERR_VM_GET_CONFIG_FAILED;
	Backup::Device::Service(pConfig).setContext(*this).enable();

	return get_op_helper()->resume_env(sUuid, pCmd->GetCommandFlags());
}
PRL_RESULT CDspDispConfigGuard::saveConfig( const QString& path, bool bNoSaveNetwork )
{
	CDspLockedPointer<CDispatcherConfig> pLockedDispConfig = getDispConfig();
	CDispNetworkPreferences*
		pNetwork = pLockedDispConfig->getDispatcherSettings()
						->getCommonPreferences()->getNetworkPreferences();
	CDispLockedOperationsList*
		pLockedOperationsList = pLockedDispConfig->getDispatcherSettings()->getCommonPreferences()
				->getLockedOperationsList();

	bool oldFlg = pNetwork->getNoSaveFlag();
	pNetwork->setNoSaveFlag( bNoSaveNetwork );

	// patch to not save operations with confirmation
	// #436109 ( we store this values in vmdirectory list to prevent deadlock in CDspAccessManager::checkAccess() )
	QList<PRL_ALLOWED_VM_COMMAND> confirmList = pLockedOperationsList->getLockedOperations();
	pLockedOperationsList->setLockedOperations( );

	CDispBackupSourcePreferences *pBackup = pLockedDispConfig->getDispatcherSettings()
						->getCommonPreferences()->getBackupSourcePreferences();
	pBackup->setSave(false);

	PRL_RESULT save_rc = pLockedDispConfig->saveToFile( path );

	pBackup->setSave(true);
	pNetwork->setNoSaveFlag( oldFlg );
	pLockedOperationsList->setLockedOperations( confirmList );

	if( PRL_FAILED(save_rc) )
	{
		WRITE_TRACE(DBG_FATAL, "Error %s on save dispatcher config. Reason: %ld: %s. path = '%s'"
			, PRL_RESULT_TO_STRING(save_rc)
			, Prl::GetLastError()
			, QSTR2UTF8( Prl::GetLastErrorAsString() )
			, QSTR2UTF8( path )
			);
		return PRL_ERR_DISP_CONFIG_WRITE_ERR;
	}

	return PRL_ERR_SUCCESS;
}
PRL_RESULT Task_VzManager::suspend_env()
{
	CProtoCommandPtr pCmd = CProtoSerializer::ParseCommand( getRequestPackage() );
	if (!pCmd->IsValid())
		return PRL_ERR_UNRECOGNIZED_REQUEST;

	PRL_RESULT res;
	QString sUuid = pCmd->GetVmUuid();

	res = check_env_state(PVE::DspCmdVmSuspend, sUuid);
	if (PRL_FAILED(res))
		return res;

	res = get_op_helper()->suspend_env(sUuid);

	SmartPtr<CVmConfiguration> pConfig = getVzHelper()->getCtConfig(getClient(), sUuid);
	if (pConfig.isValid())
		Backup::Device::Service(pConfig).disable();

	return res;
}
PRL_RESULT Task_GetBackupTreeTarget::addDisks(T& entry,
	const VmItem& vm, const QString& uuid, unsigned number)
{
	QString path = QString("%1/%2/%3").arg(getBackupDirectory()).arg(vm.getUuid()).arg(uuid);
	if (number == PRL_BASE_BACKUP_NUMBER)
		path = QString("%1/" PRL_BASE_BACKUP_DIRECTORY).arg(path);
	else
		path = QString("%1/%2").arg(path).arg(number);

	QScopedPointer<CBackupDisks> list(new (std::nothrow) CBackupDisks);
	if (!list)
		return PRL_ERR_OUT_OF_MEMORY;
	SmartPtr<CVmConfiguration> conf;
	PRL_RESULT res = loadVeConfig(uuid, path, vm.getVmType(), conf);
	if (PRL_FAILED(res))
		return res;
	conf->setRelativePath();
	/* XXX: empty home doesn't work here, so generate some random cookie */
	QString home("/" + Uuid::createUuid().toString());
	Backup::Product::Model p(Backup::Object::Model(conf), home);
	Backup::Product::componentList_type archives;
	if (BACKUP_PROTO_V4 <= vm.getVersion()) {
		p.setSuffix(::Backup::Suffix(number, 0)());
		archives = p.getVmTibs();
	} else if (vm.getVmType() == PVBT_VM)
		archives = p.getVmTibs();
	else
		archives = p.getCtTibs();

	foreach(const Backup::Product::component_type& a, archives) {
		CBackupDisk *b = new (std::nothrow) CBackupDisk;
		if (!b)
			return PRL_ERR_OUT_OF_MEMORY;
		b->setName(a.second.fileName());
		QFileInfo fi(a.first.getImage());
		/* use relative paths for disks that reside in the VM home directory */
		b->setOriginalPath(fi.dir() == home ? fi.fileName() : fi.filePath());
		b->setSize(a.first.getDevice().getSize() << 20);
		list->m_lstBackupDisks << b;
	}
PRL_RESULT CDspHaClusterHelper::getHaClusterID(QString & sHaClusterID)
{
	QStringList args;
	QProcess proc;
	args += SHAMAN_CMD_INFO;

	PRL_RESULT res = runHaman(args, proc);
	if (PRL_FAILED(res)) {
		WRITE_TRACE(DBG_FATAL, "can not get cluster info");
		return res;
	}

	QList<QByteArray> lstOut = proc.readAllStandardOutput().split('\n');
	QByteArray token = "ID :";
	foreach(QByteArray entry, lstOut) {
		if (entry.startsWith(token)) {
			sHaClusterID = QString(entry.right(entry.size() - token.size()).trimmed());
			break;
		}
	}

	return PRL_ERR_SUCCESS;
}
void CVmMigrateTargetDisk::run()
{
	m_sem_init.release();
	m_result = PRL_ERR_SUCCESS;

	while (PRL_SUCCEEDED(m_result) && !(m_queue.empty() && m_wait))
	{
		DiskQueueElem_t data;
		if (m_queue.take(data, m_token))
			m_result = write_data(&data);
		else
			break;

		if (PRL_FAILED(m_result))
		{
			WRITE_TRACE(DBG_FATAL, "[Disk migration] Failed to write block to disk %s,\
					address %llu, size %u",
				qPrintable(Uuid::fromGuid(data.hdr.disk_id).toString()),
				data.hdr.lba, data.hdr.nsect);
			m_token.signal();
		}
	}
}
PRL_RESULT Task_VzManager::restart_env()
{
	CProtoCommandPtr pCmd = CProtoSerializer::ParseCommand( getRequestPackage() );
	if (!pCmd->IsValid())
		return PRL_ERR_UNRECOGNIZED_REQUEST;
	if (CDspService::instance()->isServerStopping())
		return PRL_ERR_DISP_SHUTDOWN_IN_PROCESS;

	QString sUuid = pCmd->GetVmUuid();

	SmartPtr<CVmConfiguration> pConfig = getVzHelper()->getCtConfig(getClient(), sUuid);
	if (!pConfig)
		return PRL_ERR_VM_GET_CONFIG_FAILED;

	if (pConfig->getVmSettings()->getVmCommonOptions()->isTemplate())
		return PRL_ERR_CANT_TO_START_VM_TEMPLATE;

	PRL_RESULT res = get_op_helper()->restart_env(sUuid);
	if (PRL_FAILED(res))
		return res;

	return PRL_ERR_SUCCESS;
}
void Task_VzStateMonitor::processConfigChangedEvt(const QString &sUuid)
{
	// Handle Name change
	CDspLockedPointer< CVmDirectoryItem >
		pVmDirItem = CDspService::instance()->getVmDirManager()
		.getVmDirItemByUuid(CDspVmDirManager::getVzDirectoryUuid(), sUuid );
	if (!pVmDirItem)
		return;

	SmartPtr<CVmConfiguration> pConfig = CDspService::instance()->getVzHelper()->
		getCtConfig(CDspClient::makeServiceUser(), sUuid);
	if (!pConfig)
		return;

	QString sNewName = pConfig->getVmIdentification()->getVmName();
	if (pVmDirItem->getVmName() != sNewName && !sNewName.isEmpty()) {
		pVmDirItem->setVmName(sNewName);
		PRL_RESULT ret = CDspService::instance()->getVmDirManager().
			updateVmDirItem(pVmDirItem);
		if (PRL_FAILED(ret) )
			WRITE_TRACE(DBG_FATAL, "Can't update Container %s VmCatalogue by error: %s",
					QSTR2UTF8(sUuid), PRL_RESULT_TO_STRING(ret));
	}
}
Beispiel #19
0
static PRL_RESULT perfstats_callback(PRL_HANDLE handle, void *user_data, PRL_EVENT_TYPE process_type)
{
	PrlHandle clean(handle);
	PRL_RESULT ret;
	PRL_EVENT_TYPE e_type;

	const CmdParamData &param = *(const CmdParamData*)user_data;

	ret = PrlEvent_GetType(handle, &e_type);
	if (PRL_FAILED(ret)) {
		prl_log(L_DEBUG, "Warning! PrlSrv_Logoff failed: %s", get_error_str(ret).c_str());
		return PRL_ERR_SUCCESS;
	}

	if (e_type != process_type)
		return PRL_ERR_SUCCESS;

	print_perfstats(handle, param);

	if (s_evt)
		s_evt->Signal();

	return PRL_ERR_SUCCESS;
}
Beispiel #20
0
static PRL_RESULT print_perfstats(PRL_HANDLE handle, const CmdParamData &param)
{
	(void)param;
	unsigned int param_count;
	PRL_RESULT ret = PrlEvent_GetParamsCount(handle, &param_count);
	if (PRL_FAILED(ret))
		return prl_err(ret, "PrlEvent_GetParamsCount returned the following error: %s",
				get_error_str(ret).c_str());

	if (!param_count)
		return PRL_ERR_SUCCESS;

	// Print VM uuid if necessary
	if (param.list_all) {
		char uuid[NORMALIZED_UUID_LEN + 1] = {0};
		PRL_UINT32 size = sizeof(uuid);
		PRL_HANDLE hVm;
		if (PRL_SUCCEEDED(PrlEvent_GetVm(handle, &hVm))) {
			PrlVmCfg_GetUuid(hVm, uuid, &size);
			PrlHandle_Free(hVm);
		}
		printf("%s\n", uuid);
	}
	for (unsigned int ndx = 0; ndx < param_count; ++ndx) {
		PrlHandle hPrm;
		ret = PrlEvent_GetParam(handle, ndx, hPrm.get_ptr());
		if (PRL_FAILED(ret))
			return prl_err(ret, "PrlEvent_GetParam returned the following error: %s",
					get_error_str(ret).c_str());

		char name_buff[1024];
		unsigned int len = sizeof(name_buff) - 1;
		ret = PrlEvtPrm_GetName(hPrm.get_handle(), name_buff, &len);
		if (PRL_FAILED(ret))
			return prl_err(ret, "PrlEvtPrm_GetName returned the following error: %s",
					get_error_str(ret).c_str());
		char val_buff[1024];
		len = sizeof(val_buff) - 1;
		val_buff[len] = 0;

		PRL_PARAM_FIELD_DATA_TYPE nFieldType = PFD_UNKNOWN;
		PrlEvtPrm_GetType(hPrm.get_handle(), &nFieldType);
		if (nFieldType == PFD_BINARY) {
			if (strncmp(name_buff, PRL_NET_CLASSFUL_TRAFFIC_PTRN, sizeof(PRL_NET_CLASSFUL_TRAFFIC_PTRN) - 1) == 0) {
				PRL_STAT_NET_TRAFFIC net_stat_buf;
				len = sizeof(PRL_STAT_NET_TRAFFIC);

				if (PrlEvtPrm_GetBuffer(hPrm.get_handle(), &net_stat_buf, &len) == 0) {

					for (unsigned int i = 0; i < PRL_TC_CLASS_MAX; i++)
						fprintf(stdout, "\t%20s %2d %20llu %10u %20llu %10u\n", name_buff, i,
								net_stat_buf.incoming[i], net_stat_buf.incoming_pkt[i],
								net_stat_buf.outgoing[i], net_stat_buf.outgoing_pkt[i]);
				}
			}
		} else {
			ret = PrlEvtPrm_ToString(hPrm.get_handle(), val_buff, &len);
			if (PRL_FAILED(ret))
				return prl_err(ret, "PrlEvtPrm_ToString returned the following error: %s",
						get_error_str(ret).c_str());

			fprintf(stdout, "\t%s:\t%s\n", name_buff, val_buff);
		}

	}

	return PRL_ERR_SUCCESS;
}
PRL_RESULT CDspVmAutoTaskManagerBase::tryToRegisterVm(const SmartPtr<CVmConfiguration>& pVmConfig,
													  const QString& qsVmDirUuid,
													  int iRecommendedNextTime)
{
	if ( ! pVmConfig )
		return PRL_ERR_FAILURE;

	CVmIdent vmIdent = MakeVmIdent(pVmConfig->getVmIdentification()->getVmUuid(), qsVmDirUuid);

	// Fake client (calling at starting dispatcher from Init())
	SmartPtr<CDspClient> pClient( new CDspClient(IOSender::Handle()) );
	pClient->getAuthHelper().AuthUserBySelfProcessOwner();
	pClient->setVmDirectoryUuid(vmIdent.second);

	PRL_RESULT res = prepareRegistration( vmIdent, pClient );
	if ( PRL_FAILED( res ) )
		return res;

	if ( !isEnabled( pVmConfig, false ) )
		return unregisterVm(vmIdent);

// Check period
	int iPeriod;
	res = getPeriod( pVmConfig, iPeriod );
	if ( PRL_FAILED( res ) )
		return res;

// Register VM and start timer
	{
		QMutexLocker locker(&m_lockVmIdents);

		if (m_mapVmIdents.contains(vmIdent))
		{
			TimerInfo timerInfo = m_mapVmIdents.value(vmIdent);

			if ( timerInfo.bAutoTask )
			{
				int iOldPeriod = timerInfo.iPeriod;
				if (iOldPeriod && iOldPeriod != iPeriod)
				{
					emit killVmTimerSignal(timerInfo.iTimerId);

					m_mapVmIdents.remove(vmIdent);
				}
				else
				{
					return PRL_ERR_SUCCESS;
				}
			}
		}
	}

// Check timestamp

	QDateTime dtNow = QDateTime::currentDateTime();

	QDateTime dtTimestamp;
	{
		CDspLockedPointer<QSettings> pQSettings = CDspService::instance()->getQSettings();

		QString qsGroup = getSettingsGroupKey(vmIdent);
		pQSettings->beginGroup(qsGroup);

		QString qsKeyTimeStamp = getSettingsKeyTimestamp();
		dtTimestamp = pQSettings->value(qsKeyTimeStamp, QVariant(dtNow)).toDateTime();

		if ( ! pQSettings->contains(qsKeyTimeStamp) )
			pQSettings->setValue(qsKeyTimeStamp, QVariant(dtNow));

		pQSettings->endGroup();
	}

	int iOriginalPeriod = iPeriod;

	int iSkippedInterval = dtTimestamp.secsTo( dtNow );
	if ( iSkippedInterval > 0 )
	{
		iPeriod = (iSkippedInterval > iPeriod ? 0 : iPeriod - iSkippedInterval);
	}
	if ( iRecommendedNextTime )
		iPeriod = qMin(iPeriod, iRecommendedNextTime);

	WRITE_TRACE( DBG_FATAL, "%s manager: register VM %s with period %d (%d)",
				getManagerName(), QSTR2UTF8( pVmConfig->getVmIdentification()->getVmName() ),
				iPeriod, iOriginalPeriod );
	emit startVmTimerSignal(vmIdent, iPeriod, iOriginalPeriod);

	return PRL_ERR_SUCCESS;
}
PRL_RESULT Task_VzManager::editConfig()
{
	PRL_RESULT res;

	CProtoCommandPtr cmd = CProtoSerializer::ParseCommand( getRequestPackage() );
	if ( ! cmd->IsValid() )
		return PRL_ERR_UNRECOGNIZED_REQUEST;

	SmartPtr<CVmConfiguration> pConfig( new CVmConfiguration( cmd->GetFirstStrParam() ) );
	if( !IS_OPERATION_SUCCEEDED( pConfig->m_uiRcInit ) )
	{
		PRL_RESULT code = PRL_ERR_PARSE_VM_CONFIG;
		WRITE_TRACE(DBG_FATAL, "Error occurred while modification CT configuration: %s",
				PRL_RESULT_TO_STRING( code ) );
		return code;
	}
	QString sUuid = pConfig->getVmIdentification()->getVmUuid();
	SmartPtr<CVmConfiguration> pOldConfig = getVzHelper()->getCtConfig(getClient(), sUuid);
	if (!pOldConfig)
		return PRL_ERR_VM_GET_CONFIG_FAILED;

        QString oldname = pOldConfig->getVmIdentification()->getVmName();
        QString name = pConfig->getVmIdentification()->getVmName();

	QStringList lstFullItemIds;
	pConfig->diffDocuments(pOldConfig.getImpl(), lstFullItemIds);

	// Code below prohibits all other than Hdd and Network devices for Containers
	if (!lstFullItemIds.filter(QRegExp("Hardware\\.(?!Hdd|Network|Cpu|Memory)")).isEmpty())
		return PRL_ERR_ACTION_NOT_SUPPORTED_FOR_CT;
	// Handle the Firewall settings change on the running CT
	if (!lstFullItemIds.filter(QRegExp("\\.(?=Firewall\\.|MAC|NetAddress)")).isEmpty()) {
		VIRTUAL_MACHINE_STATE nState = VMS_UNKNOWN;
		PRL_RESULT res = getVzHelper()->getVzlibHelper().get_env_status(sUuid, nState);
		if (nState == VMS_RUNNING) {
			res = setupFirewall(pConfig);
			if (PRL_FAILED(res))
				return res;
		}
	}

	// Handle Name change
	if (oldname != name) {
		QString vm_uuid; // Skip uuid check
		QString vm_name = name;
		QString vm_home;

		// Lock the new name in the VmDirectory
		CVmDirectory::TemporaryCatalogueItem vmInfo( vm_uuid, vm_home, vm_name);
		res = checkAndLockRegisterParameters(&vmInfo);
		if (PRL_FAILED(res))
			return res;

		res = get_op_helper()->set_env_name(sUuid, name);
		if (PRL_SUCCEEDED(res)) {
			CDspLockedPointer< CVmDirectoryItem >
				pVmDirItem = CDspService::instance()->getVmDirManager()
				.getVmDirItemByUuid(m_sVzDirUuid, sUuid );

			if (!pVmDirItem) {
				WRITE_TRACE(DBG_FATAL, "Can't found VmDirItem by vmUuid = %s",
						QSTR2UTF8(sUuid));
			} else {
				pVmDirItem->setVmName(name);
				PRL_RESULT ret = CDspService::instance()->getVmDirManager().updateVmDirItem(pVmDirItem);
				if (PRL_FAILED(ret) )
					WRITE_TRACE(DBG_FATAL, "Can't update Container %s VmCatalogue by error: %s",
						QSTR2UTF8(sUuid), PRL_RESULT_TO_STRING(ret));
			}
		}

		// delete temporary registration
		CDspService::instance()->getVmDirManager()
			.unlockExclusiveVmParameters(&vmInfo);

		if (PRL_FAILED(res))
			return res;
	}

	// reset IP addresses for CT templates
	Task_EditVm::resetNetworkAddressesFromVmConfig(pConfig, pOldConfig);

	// update High Availability Cluster resource
	if (pConfig->getVmSettings()->getHighAvailability()->toString() !=
			pOldConfig->getVmSettings()->getHighAvailability()->toString()
		&& CFileHelper::isSharedFS(pConfig->getVmIdentification()->getHomePath())) {
		res = CDspService::instance()->getHaClusterHelper()->updateClusterResourceParams(
				sUuid,
				pOldConfig->getVmSettings()->getHighAvailability(),
				pConfig->getVmSettings()->getHighAvailability(),
				pConfig->getVmIdentification()->getHomePath(),
				PVT_CT);
		if (PRL_FAILED(res))
			return res;
	}

	CVmRemoteDisplay* oldD = pOldConfig->getVmSettings()->getVmRemoteDisplay();
	CVmRemoteDisplay* newD = pConfig->getVmSettings()->getVmRemoteDisplay();

	if (oldD->getPassword() != newD->getPassword()) {
		if (newD->getPassword().length() > PRL_VM_REMOTE_DISPLAY_MAX_PASS_LEN) {
			WRITE_TRACE(DBG_FATAL, "The specified remote display password is too long.");
			getLastError()->addEventParameter(
				new CVmEventParameter(
					PVE::UnsignedInt,
					QString::number(PRL_VM_REMOTE_DISPLAY_MAX_PASS_LEN),
					EVT_PARAM_MESSAGE_PARAM_0));

			return PRL_ERR_VMCONF_REMOTE_DISPLAY_PASSWORD_TOO_LONG;
		}
	}

	Backup::Device::Service service(pOldConfig);
	service.setContext(*this).setVmHome(pConfig->getVmIdentification()->getHomePath());
	Backup::Device::Details::Transition t = service.getTransition(pConfig);
	res = t.plant();
	if (PRL_FAILED(res))
		return res;

	res = get_op_helper()->apply_env_config(pConfig, pOldConfig, cmd->GetCommandFlags());
	if (PRL_FAILED(res))
		return res;

	res = t.remove();
	if (PRL_FAILED(res))
		return res;

	// Invalidate cache
	CDspService::instance()->getVzHelper()->getConfigCache().
		remove(pConfig->getVmIdentification()->getHomePath());

	res = changeVNCServerState(pOldConfig, pConfig, sUuid);
	if (PRL_FAILED(res))
		return res;

	// Handle memory limit change
	unsigned int newRamSize = pConfig->getVmHardwareList()->getMemory()->getRamSize();
	unsigned int oldRamSize = pOldConfig->getVmHardwareList()->getMemory()->getRamSize();
	if (newRamSize != oldRamSize) {
		VIRTUAL_MACHINE_STATE nState = VMS_UNKNOWN;
		PRL_RESULT res = getVzHelper()->getVzlibHelper().get_env_status(sUuid, nState);
		if (PRL_SUCCEEDED(res) && (nState == VMS_RUNNING))
			adjustReservedMemLimit((long long)newRamSize - oldRamSize);
	}

	QStringList lstAdd, lstDel;
	// Handle application templates
	QStringList newAppTemplates = pConfig->getCtSettings()->getAppTemplate();
	QStringList oldAppTemplates = pOldConfig->getCtSettings()->getAppTemplate();

	for (int i = 0; i < newAppTemplates.size(); i++) {
		if (newAppTemplates.at(i).startsWith('.'))
			newAppTemplates[i].remove(0, 1);
	}
	for (int i = 0; i < oldAppTemplates.size(); i++) {
		if (oldAppTemplates.at(i).startsWith('.'))
			oldAppTemplates[i].remove(0, 1);
	}

	if (newAppTemplates == oldAppTemplates)
		goto ok;

	foreach(QString str, newAppTemplates)
		if (!oldAppTemplates.contains(str))
			lstAdd.append(str);
	foreach(QString str, oldAppTemplates)
		if (!newAppTemplates.contains(str))
			lstDel.append(str);

	do {
		CVzTemplateHelper TmplHelper = getVzHelper()->getVzTemplateHelper();
		res = TmplHelper.remove_templates_env(sUuid, lstDel);
		if (PRL_FAILED(res))
			return res;

		res = TmplHelper.install_templates_env(sUuid, lstAdd);
	} while (0);

ok:
	if ( PRL_SUCCEEDED(res) ) {
		SmartPtr<CVmConfiguration> pNewConfig = getVzHelper()->getCtConfig(getClient(), sUuid);
		QStringList lstParams(pNewConfig ?
				pNewConfig->toString() : pConfig->toString());
		getResponseCmd()->SetParamsList( lstParams );

		sendEvent(PET_DSP_EVT_VM_CONFIG_CHANGED, sUuid);
	}

	return res;
}
PRL_RESULT Task_MigrateCtTarget::run_body()
{
	PRL_RESULT nRetCode = PRL_ERR_SUCCESS;
	bool bConnected;
	QTimer *pTimer;
	CDispToDispCommandPtr pReply;
	SmartPtr<IOPackage> pPackage;
	IOSendJob::Handle hJob;

	if (operationIsCancelled()) {
		nRetCode = PRL_ERR_OPERATION_WAS_CANCELED;
		goto exit;
	}

	bConnected = QObject::connect(m_pParent,
		SIGNAL(onPackageReceived(
			const SmartPtr<CDspDispConnection> &,
			const QString &,
			const SmartPtr<IOPackage> &)),
		SLOT(handleStartPackage(
			const SmartPtr<CDspDispConnection> &,
			const QString &,
			const SmartPtr<IOPackage> &)),
		Qt::DirectConnection);
	PRL_ASSERT(bConnected);

	m_nReservedFlags |= PVM_CT_MIGRATE;
	pReply = CDispToDispProtoSerializer::CreateVmMigrateCheckPreconditionsReply(
		m_lstCheckPrecondsErrors, QStringList(), m_nReservedFlags);
	pPackage =
		DispatcherPackage::createInstance(
			pReply->GetCommandId(), pReply->GetCommand()->toString(), m_pCheckPackage);
	hJob = m_pCheckDispConnection->sendPackage(pPackage);
	if (!hJob.isValid()) {
		nRetCode = PRL_ERR_OPERATION_FAILED;
		goto exit;
	}

	/* set timer */
	pTimer = new QTimer();
	pTimer->setSingleShot(true);
	bConnected = QObject::connect(pTimer, SIGNAL(timeout()), SLOT(handleStartCommandTimeout()), Qt::DirectConnection);
	pTimer->start(VM_MIGRATE_START_CMD_WAIT_TIMEOUT);

	/* will wait StartMigration command */
	nRetCode = exec();
	pTimer->stop();
	if (bConnected)
		QObject::disconnect(pTimer, SIGNAL(timeout()), this, SLOT(handleStartCommandTimeout()));
	delete pTimer;

	QObject::disconnect(m_pParent,
		SIGNAL(onPackageReceived(
			const SmartPtr<CDspDispConnection> &,
			const QString &,
			const SmartPtr<IOPackage> &)),
		this,
		SLOT(handleStartPackage(
			const SmartPtr<CDspDispConnection> &,
			const QString &,
			const SmartPtr<IOPackage> &)));

	if (PRL_FAILED(nRetCode))
		goto exit;

	if (operationIsCancelled()) {
		nRetCode = PRL_ERR_OPERATION_WAS_CANCELED;
		goto exit;
	}

	if ( !(m_nReservedFlags & PVM_DONT_COPY_VM) ) {
		/* to create Vm bundle */
		if (!CFileHelper::WriteDirectory(m_sTargetVmHomePath, &getClient()->getAuthHelper())) {
			nRetCode = PRL_ERR_BACKUP_CANNOT_CREATE_DIRECTORY;
			CVmEvent *pEvent = getLastError();
			pEvent->setEventCode(nRetCode);
			pEvent->addEventParameter(
				new CVmEventParameter(PVE::String, m_sTargetVmHomePath, EVT_PARAM_MESSAGE_PARAM_0));
			WRITE_TRACE(DBG_FATAL, "[%s] Cannot create \"%s\" directory",
					__FUNCTION__, QSTR2UTF8(m_sTargetVmHomePath));
			goto exit;
		}
		/* set original permissions to Vm bundle (https://jira.sw.ru/browse/PSBM-8269) */
		if (m_nBundlePermissions) {
			QFile vmBundle(m_sTargetVmHomePath);
			if (!vmBundle.setPermissions((QFile::Permissions)m_nBundlePermissions)) {
				WRITE_TRACE(DBG_FATAL,
					"[%s] Cannot set permissions for Vm bundle \"%s\", will use default",
					__FUNCTION__, QSTR2UTF8(m_sTargetVmHomePath));
			}
		}
	}
	m_nSteps |= MIGRATE_STARTED;
	if ((m_nPrevVmState == VMS_RUNNING) || (m_nPrevVmState == VMS_PAUSED)) {
		nRetCode = PRL_ERR_VM_MIGRATE_UNSUITABLE_VM_STATE;
	} else {
		nRetCode = migrateStoppedVm();

		/* migration completed and connection state is indifferent for us
		   https://jira.sw.ru/browse/PSBM-8925 */
		QObject::disconnect(
			&CDspService::instance()->getIOServer(),
			SIGNAL(onClientDisconnected(IOSender::Handle)),
			this,
			SLOT(clientDisconnected(IOSender::Handle)));
	}

	if (PRL_FAILED(nRetCode))
		goto exit;

	/* rename conf file since source sent it with his origin ctid */
	if (m_nOriginCtid != m_nCtid) {
		QString srcPath = m_sTargetVmHomePath + QString("/%1.conf").arg(m_nOriginCtid);
		QString dstPath = m_sTargetVmHomePath + QString("/%1.conf").arg(m_nCtid);
		QFile::rename(srcPath, dstPath);
	}

	nRetCode = CVzHelper::dst_complete_migrate_env(m_sVmUuid, m_nCtid, m_nOriginCtid, &m_pOpaqueLock);
	if (PRL_FAILED(nRetCode)) {
		WRITE_TRACE(DBG_FATAL, "Can not compelete destination CT migration for ctid %u uuid %s",
			    m_nCtid,  QSTR2UTF8(m_sVmUuid));
		goto exit;
	}

	if (PVMT_CLONE_MODE & getRequestFlags())
		m_pVmConfig->getVmIdentification()->setSourceVmUuid(m_sOriginVmUuid);

	if (PVMT_CLONE_MODE & getRequestFlags()) {
		if ( PVMT_SWITCH_TEMPLATE & getRequestFlags() )
			m_pVmConfig->getVmSettings()->getVmCommonOptions()->setTemplate(
				!m_pVmConfig->getVmSettings()->getVmCommonOptions()->isTemplate() );

		Task_CloneVm::ResetNetSettings(m_pVmConfig);
	}

	/* do not fail since here - Ct already migrated */
	{
		QString sServerUuid = CDspService::instance()->getDispConfigGuard().getDispConfig()
			->getVmServerIdentification()->getServerUuid();
		QString sLastServerUuid = m_pVmConfig->getVmIdentification()->getServerUuid();
		m_pVmConfig->getVmIdentification()->setServerUuid(sServerUuid);
		m_pVmConfig->getVmIdentification()->setLastServerUuid(sLastServerUuid);
		SmartPtr<CVmConfiguration> pOldConfig = CDspService::instance()->getVzHelper()
			->getVzlibHelper().get_env_config(m_nCtid);
		if (pOldConfig == NULL) {
			WRITE_TRACE(DBG_FATAL, "Can't get config for CT %s [%d]", QSTR2UTF8(m_sVmUuid), m_nCtid);
		} else {
			get_op_helper().apply_env_config(m_pVmConfig, pOldConfig);
		}
	}

	// insert new item in user's VM Directory
	m_pVmConfig = CDspService::instance()->getVzHelper()->getVzlibHelper().get_env_config(m_nCtid);
	if (PRL_FAILED(CDspService::instance()->getVzHelper()->insertVmDirectoryItem(m_pVmConfig))) {
		WRITE_TRACE(DBG_FATAL, "Can't insert CT to VmDirectory by error %#x, %s",
			    nRetCode, PRL_RESULT_TO_STRING(nRetCode) );
	}

exit:
	setLastErrorCode(nRetCode);
	return nRetCode;
}
/* process VmMigrateCheckPreconditionsCommand */
PRL_RESULT Task_MigrateCtTarget::prepareTask()
{
	//https://bugzilla.sw.ru/show_bug.cgi?id=267152
	CAuthHelperImpersonateWrapper _impersonate( &getClient()->getAuthHelper() );

	PRL_RESULT nRetCode = PRL_ERR_SUCCESS;
	QString sVmDirPath;

	if (CDspService::instance()->isServerStopping()) {
		WRITE_TRACE(DBG_FATAL, "Dispatcher shutdown is in progress - CT migrate rejected!");
		nRetCode = PRL_ERR_DISP_SHUTDOWN_IN_PROCESS;
		goto exit;
	}

	m_pVmConfig = SmartPtr<CVmConfiguration>(new CVmConfiguration(m_sVmConfig));
	if (PRL_FAILED(m_pVmConfig->m_uiRcInit)) {
		nRetCode = PRL_ERR_PARSE_VM_CONFIG;
		WRITE_TRACE(DBG_FATAL, "Wrong VM condiguration was received: [%s]", QSTR2UTF8(m_sVmConfig));
		goto exit;
	}
	m_sOriginVmUuid = m_pVmConfig->getVmIdentification()->getVmUuid();
	m_nCtid = m_nOriginCtid = m_pVmConfig->getVmIdentification()->getEnvId();
	m_sVmName = m_pVmConfig->getVmIdentification()->getVmName();

	nRetCode = CVzHelper::dst_start_migrate_env(&m_nCtid, &m_pOpaqueLock);
	if (PRL_FAILED(nRetCode)) {
		WRITE_TRACE(DBG_FATAL, "Can not start destination CT migration for uuid %s", QSTR2UTF8(m_sVmUuid));
		goto exit;
	}

	if (m_nCtid != m_nOriginCtid)
		m_pVmConfig->getVmIdentification()->setEnvId(m_nCtid);

	{
		CDspLockedPointer<CVmDirectory> pDir = CDspService::instance()->getVmDirManager().getVzDirectory();
		if (!pDir) {
			nRetCode = PRL_ERR_VM_UUID_NOT_FOUND;
			WRITE_TRACE(DBG_FATAL, "Couldn't to find VZ directiory UUID");
			goto exit;
		}
		m_sVzDirUuid = pDir->getUuid();
	}
	m_sVmUuid = (PVMT_CLONE_MODE & getRequestFlags()) ? Uuid::createUuid().toString() : m_sOriginVmUuid;

	WRITE_TRACE(DBG_FATAL, "Start migrate origin CTID=%u to CTID=%u for uuid %s",
		    m_nOriginCtid, m_nCtid, QSTR2UTF8(m_sVmUuid));

	/*  to get target VM home directory path */
	if (!m_sVmDirPath.isEmpty())
		m_sTargetVmHomePath = m_sVmDirPath;
	else {
		m_sTargetVmHomePath = CVzHelper::getCtPrivatePath(m_nCtid);
	}
	m_sTargetVmHomePath = QFileInfo(m_sTargetVmHomePath).absoluteFilePath();
	m_sVmConfigPath = QString("%1/" VMDIR_DEFAULT_VM_CONFIG_FILE).arg(m_sTargetVmHomePath);

	/* lock Vm exclusive parameters */
	m_pVmInfo = SmartPtr<CVmDirectory::TemporaryCatalogueItem>(new CVmDirectory::TemporaryCatalogueItem(
			m_sVmUuid, m_sVmConfigPath, m_sVmName));

	nRetCode = CDspService::instance()->getVmDirManager()
			.checkAndLockNotExistsExclusiveVmParameters(QStringList(), m_pVmInfo.getImpl());
	if (PRL_FAILED(nRetCode))
	{
		switch (nRetCode)
		{
		case PRL_ERR_VM_ALREADY_REGISTERED_VM_UUID:
			WRITE_TRACE(DBG_FATAL, "UUID '%s' already registered", QSTR2UTF8(m_pVmInfo->vmUuid));
			getLastError()->addEventParameter(
				new CVmEventParameter( PVE::String, m_pVmInfo->vmUuid, EVT_PARAM_RETURN_PARAM_TOKEN));
			break;

		case PRL_ERR_VM_ALREADY_REGISTERED_VM_PATH:
			WRITE_TRACE(DBG_FATAL, "path '%s' already registered", QSTR2UTF8(m_pVmInfo->vmXmlPath));
			getLastError()->addEventParameter(
				new CVmEventParameter( PVE::String, m_pVmInfo->vmName, EVT_PARAM_MESSAGE_PARAM_0));
			getLastError()->addEventParameter(
				new CVmEventParameter( PVE::String, m_pVmInfo->vmXmlPath, EVT_PARAM_MESSAGE_PARAM_1));
			break;

		case PRL_ERR_VM_ALREADY_REGISTERED_VM_NAME:
			WRITE_TRACE(DBG_FATAL, "name '%s' already registered", QSTR2UTF8(m_pVmInfo->vmName));
			getLastError()->addEventParameter(
				new CVmEventParameter( PVE::String, m_pVmInfo->vmName, EVT_PARAM_MESSAGE_PARAM_0));
			break;

		case PRL_ERR_VM_ALREADY_REGISTERED:
			WRITE_TRACE(DBG_FATAL, "container '%s' already registered", QSTR2UTF8(m_pVmInfo->vmName));
			getLastError()->addEventParameter(
					new CVmEventParameter( PVE::String, m_pVmInfo->vmName, EVT_PARAM_MESSAGE_PARAM_0));
			break;

		case PRL_ERR_VM_ALREADY_REGISTERED_UNIQUE_PARAMS:; // use default

		default:
			WRITE_TRACE(DBG_FATAL, "can't register container with UUID '%s', name '%s', path '%s",
				QSTR2UTF8(m_pVmInfo->vmUuid), QSTR2UTF8(m_pVmInfo->vmName), QSTR2UTF8(m_pVmInfo->vmXmlPath));
			getLastError()->addEventParameter(
				 new CVmEventParameter( PVE::String, m_pVmInfo->vmUuid, EVT_PARAM_RETURN_PARAM_TOKEN));
			getLastError()->addEventParameter(
				 new CVmEventParameter( PVE::String, m_pVmInfo->vmXmlPath, EVT_PARAM_RETURN_PARAM_TOKEN));
			getLastError()->addEventParameter(
				 new CVmEventParameter( PVE::String, m_pVmInfo->vmName, EVT_PARAM_RETURN_PARAM_TOKEN));
		}
		goto exit;
	}
	m_nSteps |= MIGRATE_VM_EXCL_PARAMS_LOCKED;

	if (!(PVMT_SWITCH_TEMPLATE & getRequestFlags())) {
		/* skip checking for copy to template case (https://jira.sw.ru/browse/PSBM-9597) */
		//checkTargetCpusNumber();
		//checkTargetCpuCompatibility();
	}

exit:
	setLastErrorCode(nRetCode);
	return nRetCode;
}
PRL_RESULT Task_MigrateCtSource::run_body()
{
	SmartPtr<CVmEvent> pEvent;
	SmartPtr<IOPackage> pPackage;
	IOSendJob::Response pResponse;
	CDispToDispCommandPtr pCmd;
	CDispToDispResponseCommand *pRespCmd;

	//https://bugzilla.sw.ru/show_bug.cgi?id=267152
	CAuthHelperImpersonateWrapper _impersonate( &getClient()->getAuthHelper() );

	if (operationIsCancelled())
		setLastErrorCode(PRL_ERR_OPERATION_WAS_CANCELED);

	PRL_RESULT nRetCode = PRL_ERR_SUCCESS;

	if (PRL_FAILED(nRetCode = CheckVmMigrationPreconditions()))
		goto exit;

	/* set migration mode */
	switch (m_nPrevVmState) {
	case VMS_RUNNING:
	case VMS_PAUSED:
		nRetCode = PRL_ERR_VM_MIGRATE_WARM_MODE_NOT_SUPPORTED;
		goto exit;
	default:
		m_nMigrationFlags |= PVMT_COLD_MIGRATION;
	}

	if (operationIsCancelled())
		setLastErrorCode(PRL_ERR_OPERATION_WAS_CANCELED);

	pEvent = SmartPtr<CVmEvent>(new CVmEvent(PET_DSP_EVT_VM_MIGRATE_STARTED, m_sVmUuid, PIE_DISPATCHER));
	pEvent->addEventParameter(new CVmEventParameter(PVE::Boolean, "true", EVT_PARAM_MIGRATE_IS_SOURCE));
	pPackage = DispatcherPackage::createInstance(PVE::DspVmEvent, pEvent->toString());

	m_nSteps |= MIGRATE_VM_STATE_CHANGED;
	/* and notify clients about VM migration start event */
	CDspService::instance()->getClientManager().sendPackageToVmClients(pPackage, m_sVzDirUuid, m_sVmUuid);

	/* remove target Vm config from watcher (#448235) */
	CDspService::instance()->getVmConfigWatcher().unregisterVmToWatch(m_sVmConfigPath);
	m_nSteps |= MIGRATE_UNREGISTER_VM_WATCH;

	nRetCode = migrateStoppedCt();
	if (PRL_FAILED(nRetCode))
		goto exit;

	/* wait finish reply from target (https://jira.sw.ru/browse/PSBM-9596) */
	quint32 nTimeout = m_nTimeout;

	/* wait target task finish */
	if (PVMT_CHANGE_SID & getRequestFlags())
		/* wait reply during changeSID task timeout (https://jira.sw.ru/browse/PSBM-9733) */
		nTimeout = CHANGESID_TIMEOUT;
	if (m_pIoClient->waitForResponse(m_hCheckReqJob, nTimeout) != IOSendJob::Success) {
		WRITE_TRACE(DBG_FATAL, "Finish acknowledgement receiving failure");
		nRetCode = PRL_ERR_CT_MIGRATE_INTERNAL_ERROR;
		goto exit;
	}
	pResponse = m_pIoClient->takeResponse(m_hCheckReqJob);
	if (pResponse.responseResult != IOSendJob::Success) {
		WRITE_TRACE(DBG_FATAL, "Finish acknowledgement receiving failure");
		nRetCode = PRL_ERR_CT_MIGRATE_INTERNAL_ERROR;
		goto exit;
	}
	pPackage  = pResponse.responsePackages[0];
	if (pPackage->header.type != DispToDispResponseCmd) {
		WRITE_TRACE(DBG_FATAL, "Invalid package type : %d", pPackage->header.type);
		nRetCode = PRL_ERR_CT_MIGRATE_INTERNAL_ERROR;
		goto exit;
	}

	pCmd = CDispToDispProtoSerializer::ParseCommand(
		DispToDispResponseCmd, UTF8_2QSTR(pPackage->buffers[0].getImpl()));
	pRespCmd = CDispToDispProtoSerializer::CastToDispToDispCommand<CDispToDispResponseCommand>(pCmd);
	nRetCode = pRespCmd->GetRetCode();
	if (PRL_FAILED(nRetCode))
		getLastError()->fromString(pRespCmd->GetErrorInfo()->toString());

exit:
	setLastErrorCode(nRetCode);
	return nRetCode;
}
PRL_RESULT Task_MigrateCtSource::prepareTask()
{
	//https://bugzilla.sw.ru/show_bug.cgi?id=267152
	CAuthHelperImpersonateWrapper _impersonate( &getClient()->getAuthHelper() );

	PRL_RESULT nRetCode = PRL_ERR_SUCCESS;

	if (CDspService::instance()->isServerStopping())
	{
		WRITE_TRACE(DBG_FATAL, "Dispatcher shutdown is in progress - VM migrate rejected!");
		nRetCode = PRL_ERR_DISP_SHUTDOWN_IN_PROCESS;
		goto exit;
	}

	if (CDspService::instance()->getShellServiceHelper().isLocalAddress(m_sServerHostname)) {
		WRITE_TRACE(DBG_FATAL,
			"Host %s is a local host, migration is impossible", QSTR2UTF8(m_sServerHostname));
		nRetCode = PRL_ERR_VM_MIGRATE_TO_THE_SAME_NODE;
		goto exit;
	}

	/* will use Vz dir uuid for Vm */
	{
		CDspLockedPointer<CVmDirectory> pDir = CDspService::instance()->getVmDirManager().getVzDirectory();
		if (!pDir) {
			nRetCode = PRL_ERR_VM_UUID_NOT_FOUND;
			WRITE_TRACE(DBG_FATAL, "Couldn't to find VZ directiory UUID");
			goto exit;
		}
		m_sVzDirUuid = pDir->getUuid();

		nRetCode = CDspService::instance()->getVmDirHelper().registerExclusiveVmOperation(
			m_sVmUuid, m_sVzDirUuid, PVE::DspCmdDirVmMigrate, getClient());
		if ( PRL_FAILED(nRetCode) ) {
			WRITE_TRACE(DBG_FATAL, "[%s] registerExclusiveVmOperation failed. Reason: %#x (%s)",
				    __FUNCTION__, nRetCode, PRL_RESULT_TO_STRING(nRetCode));
			goto exit;
		}
		m_bExVmOperationRegistered = true;
	}

	m_pVmConfig = CDspService::instance()->getVzHelper()->getCtConfig(getClient(), m_sVmUuid);
	if (!m_pVmConfig.isValid()) {
		WRITE_TRACE(DBG_FATAL, "Can not load config for uuid %s", QSTR2UTF8(m_sVmUuid));
		goto exit;
	}
	m_sVmHomePath = m_pVmConfig->getVmIdentification()->getHomePath();
	m_nCtid = m_pVmConfig->getVmIdentification()->getEnvId();

	nRetCode = CDspService::instance()->getVzHelper()->getVzlibHelper().get_env_status(m_sVmUuid, m_nPrevVmState);
	if (PRL_FAILED(nRetCode)) {
		WRITE_TRACE(DBG_FATAL, "Can not get status for uuid %s", QSTR2UTF8(m_sVmUuid));
		goto exit;
	}

	if (m_nPrevVmState != VMS_STOPPED) {
		WRITE_TRACE(DBG_FATAL, "CT must be stopped for migration");
		nRetCode = PRL_ERR_VM_MIGRATE_UNSUITABLE_VM_STATE;
		goto exit;
	}

	nRetCode = CVzHelper::src_start_migrate_env(m_nCtid, &m_pOpaqueLock);
	if (PRL_FAILED(nRetCode)) {
		WRITE_TRACE(DBG_FATAL, "Can not start source CT migration for uuid %s", QSTR2UTF8(m_sVmUuid));
		goto exit;
	}

	{
		/* LOCK inside brackets */
		CDspLockedPointer<CDspHostInfo> lockedHostInfo = CDspService::instance()->getHostInfo();
		m_cHostInfo.fromString( lockedHostInfo->data()->toString() );
	}

	nRetCode = Connect(
		m_sServerHostname, m_nServerPort, m_sServerSessionUuid, QString(), QString(), m_nMigrationFlags);
	if (PRL_FAILED(nRetCode))
		goto exit;

exit:
	setLastErrorCode(nRetCode);
	return nRetCode;
}
Beispiel #27
0
int PrlSrv::print_statistics(const CmdParamData &param, PrlVm *vm)
{
	PRL_RESULT ret;
	std::string err;

	if (param.list_all && !vm) {
		ret = update_vm_list(param.vmtype);
		if (PRL_FAILED(ret))
			return ret;
	}

	if (!param.statistics.loop)
		s_evt = new CEventSyncObject();

	const PrlHook *hHook = get_cleanup_ctx().register_hook(call_exit, NULL);

	if (param.action == SrvPerfStatsAction) {
		ret = PrlSrv_RegEventHandler(get_handle(), &perfstats_srv_callback, (void*)&param);
		if (PRL_FAILED(ret))
			return prl_err(ret, "PrlSrv_RegEventHandler returned the following error: %s",
					get_error_str(ret).c_str());
		PrlHandle hJob(PrlSrv_SubscribeToPerfStats(get_handle(), param.statistics.filter.c_str()));
		if (PRL_FAILED(get_job_retcode_predefined(hJob.get_handle(), err)))
			return prl_err(ret, "PrlSrv_SubscribeToPerfStats returned the following error: %s", err.c_str());
	}

	if (param.action == VmPerfStatsAction || param.list_all) {
		for (PrlVmList::iterator it = m_VmList.begin(), end = m_VmList.end(); it != end; ++it) {
			if (!param.list_all && (*it) != vm)
				continue;

			ret = PrlVm_RegEventHandler((*it)->get_handle(), &perfstats_vm_callback, (void*)&param);
			if (PRL_FAILED(ret))
				return prl_err(ret, "PrlVm_RegEventHandler returned the following error: %s",
						get_error_str(ret).c_str());
			PrlHandle hJob(PrlVm_SubscribeToPerfStats((*it)->get_handle(), param.statistics.filter.c_str()));
			if (PRL_FAILED(get_job_retcode_predefined(hJob.get_handle(), err)))
				return prl_err(ret, "PrlVm_SubscribeToPerfStats returned the following error: %s", err.c_str());
			if (s_evt) {
				s_evt->Wait(10000);
				s_evt->Reset();
				PrlVm_UnregEventHandler((*it)->get_handle(), &perfstats_vm_callback, (void*)&param);
				PrlHandle j(PrlVm_UnsubscribeFromPerfStats((*it)->get_handle()));
				get_job_retcode_predefined(j.get_handle(), err);
			}
		}
	}

	if (param.statistics.loop) {
		int ch = 0 ;
		while (ch!=0x0A && ch!=0x0D && ch!=0x03) {
			ch = _getch();
		}
		fprintf(stdout, "\n");
	}

	get_cleanup_ctx().unregister_hook(hHook);

	if (param.action == SrvPerfStatsAction)
		PrlSrv_UnregEventHandler(get_handle(), &perfstats_srv_callback, NULL);

	return 0;
}
PRL_RESULT Mixin_CreateVmSupport::setDefaultVmPermissions(
	SmartPtr<CDspClient> pUser,
	QString vmPathToConfig,
	bool bKeepOthersPermissions
)
{
	PRL_ASSERT( pUser );
	PRL_ASSERT( ! vmPathToConfig.isEmpty() );

	if( ! pUser || vmPathToConfig.isEmpty() )
		return PRL_ERR_INVALID_ARG;

	// FIXME: isFsSupportPermsAndOwner() should be moved near setFullAccessRightsToVm() and united with it.
	{
		//https://bugzilla.sw.ru/show_bug.cgi?id=267152
		CAuthHelperImpersonateWrapper _impersonate( &pUser->getAuthHelper() );

		// # https://bugzilla.sw.ru/show_bug.cgi?id=112901
		// https://jira.sw.ru/browse/PSBM-9040
		if( !CFileHelper::isFsSupportPermsAndOwner( vmPathToConfig ) )
		{
			WRITE_TRACE(DBG_FATAL, "File system does not support permissions. Setting default Vm permission will be ignored. (path=%s)"
				, QSTR2UTF8( vmPathToConfig ) );
			return PRL_ERR_SUCCESS;
		}
	}

	// get vm directory path

	// To prevent stupid errors see https://bugzilla.sw.ru/show_bug.cgi?id=483700 for more details
	PRL_ASSERT(QFileInfo( vmPathToConfig ).isFile());
	QString strVmDirPath;
	if ( QFileInfo( vmPathToConfig ).isFile() )
		strVmDirPath = CFileHelper::GetFileRoot( vmPathToConfig );
	else
	{
		strVmDirPath = vmPathToConfig;
		vmPathToConfig = QString("%1/%2").arg(strVmDirPath).arg(VMDIR_DEFAULT_VM_CONFIG_FILE);
	}

	if ( !CDspAccessManager::setOwner( strVmDirPath, &pUser->getAuthHelper(), true )  )
	{
		WRITE_TRACE(DBG_FATAL, "Can't change owner to vm dir files [%s]. error=[%s]"
			, QSTR2UTF8( strVmDirPath )
			, QSTR2UTF8( Prl::GetLastErrorAsString() ) );
		return PRL_ERR_CANT_CHANGE_OWNER_OF_FILE;
	}

	//////////////////////////////////////////////////////////////////////////
	// set default access rigths
	//////////////////////////////////////////////////////////////////////////
	CVmDirectoryItem vmDirItem;
	vmDirItem.setVmHome( vmPathToConfig );
	PRL_SEC_AM ownerAccess = CDspAccessManager::VmAccessRights::makeModeRWX() ;
	PRL_SEC_AM otherAccess = CDspAccessManager::VmAccessRights::makeModeNO_ACCESS() ;

	PRL_RESULT err = CDspService::instance()->getAccessManager()
		.setFullAccessRightsToVm( pUser, &vmDirItem, &ownerAccess,
		// Do not change others permissions during registration at desktop mode
		// https://bugzilla.sw.ru/show_bug.cgi?id=120191
		 ! bKeepOthersPermissions ? &otherAccess : NULL );
	if( PRL_FAILED( err ) )
	{
		WRITE_TRACE(DBG_FATAL, "Can't change permission to vm dir files [%s]. error=[%s]"
			, QSTR2UTF8( strVmDirPath )
			, QSTR2UTF8( Prl::GetLastErrorAsString() ) );
		return PRL_ERR_CANT_CHANGE_FILE_PERMISSIONS;
	}

	return PRL_ERR_SUCCESS;
}
PRL_RESULT Task_VzManager::clone_env()
{
	PRL_RESULT res;

	CProtoCommandPtr cmd = CProtoSerializer::ParseCommand( getRequestPackage() );
	if (!cmd->IsValid())
		return PRL_ERR_UNRECOGNIZED_REQUEST;

	CProtoVmCloneCommand *pCmd = CProtoSerializer::CastToProtoCommand<CProtoVmCloneCommand>(cmd);

	QString sUuid = pCmd->GetVmUuid();
	QString sNewHome = pCmd->GetVmHomePath();
	QString sNewName = pCmd->GetVmName();
	unsigned int nFlags = pCmd->GetCommandFlags();

	if (sNewName.isEmpty())
		return PRL_ERR_VM_NAME_IS_EMPTY;

	res = check_env_state(PVE::DspCmdDirVmClone, sUuid);
	if (PRL_FAILED(res))
		return res;

	SmartPtr<CVmConfiguration> pConfig = getVzHelper()->getCtConfig(getClient(), sUuid);
	if (!pConfig)
	{
		WRITE_TRACE(DBG_FATAL, "Unable to find CT by uuid %s", QSTR2UTF8(sUuid));
		return PRL_ERR_VM_GET_CONFIG_FAILED;
	}

	SmartPtr<CVmConfiguration> pNewConfig(new CVmConfiguration);

	if (!pCmd->GetNewVmUuid().isEmpty())
		pNewConfig->getVmIdentification()->setVmUuid(pCmd->GetNewVmUuid());

	CVmDirectory::TemporaryCatalogueItem vmInfo(
			pNewConfig->getVmIdentification()->getVmUuid(),
			QString(),
			sNewName);

	res = checkAndLockRegisterParameters(&vmInfo);
	if (PRL_FAILED(res))
		return res;

	res = get_op_helper()->clone_env(pConfig, sNewHome, sNewName, nFlags, pNewConfig);
	if (PRL_SUCCEEDED(res)) {
		res = getVzHelper()->insertVmDirectoryItem(pNewConfig);
		if (PRL_FAILED(res))
			get_op_helper()->delete_env(
					pNewConfig->getVmIdentification()->getVmUuid());
	}
	// delete temporary registration
	CDspService::instance()->getVmDirManager()
		.unlockExclusiveVmParameters(&vmInfo);

	if (PRL_FAILED(res) || !pNewConfig.isValid())
		return res;

	SmartPtr<CVmConfiguration> pOldConfig(new CVmConfiguration(pNewConfig->toString()));

	bool isTemplate = (nFlags & PCVF_CLONE_TO_TEMPLATE);
	pNewConfig->getVmSettings()->getVmCommonOptions()->setTemplate(isTemplate);

	Task_CloneVm::ResetNetSettings(pNewConfig);
	Backup::Device::Dao(pNewConfig).deleteAll();

	get_op_helper()->apply_env_config(pNewConfig, pOldConfig, PVCF_DESTROY_HDD_BUNDLE);

	getResponseCmd()->SetVmConfig(pNewConfig->toString());
	{
	       CVmEvent event(PET_DSP_EVT_VM_ADDED,
			       pNewConfig->getVmIdentification()->getVmUuid(),
			       PIE_DISPATCHER);
	       SmartPtr<IOPackage> p = DispatcherPackage::createInstance(PVE::DspVmEvent, event);
	       CDspService::instance()->getClientManager().sendPackageToAllClients(p);
	}
	// Set some parameters in the response (see Task_CloneVm)
	CDspLockedPointer<CVmEvent> pParams = getTaskParameters();

	pParams->addEventParameter(
			new CVmEventParameter( PVE::String,
				pNewConfig->getVmIdentification()->getVmUuid(),
				EVT_PARAM_DISP_TASK_CLONE_VM_UUID ) );
	pParams->addEventParameter(
			new CVmEventParameter( PVE::String,
				pNewConfig->getVmIdentification()->getVmName(),
				EVT_PARAM_DISP_TASK_CLONE_NEW_VM_NAME ) );
	pParams->addEventParameter(
			new CVmEventParameter( PVE::String,
				pNewConfig->getVmIdentification()->getHomePath(),
				EVT_PARAM_DISP_TASK_CLONE_NEW_VM_ROOT_DIR ) );
	pParams->addEventParameter(
			new CVmEventParameter( PVE::Boolean,
				QString("%1").arg(isTemplate),
				EVT_PARAM_DISP_TASK_CLONE_AS_TEMPLATE ) );
	return PRL_ERR_SUCCESS;
}