PRL_RESULT CDspVmAutoTaskManagerBase::unregisterVm(const CVmIdent& vmIdent,
												   bool bEditVmConfig,
												   const SmartPtr<CDspClient>& pClient)
{
	WRITE_TRACE( DBG_DEBUG, "Unregistering VM '%s' from %s manager",
			QSTR2UTF8( vmIdent.first ), getManagerName() );

// Clear settings
	{
		CDspLockedPointer<QSettings> pQSettings = CDspService::instance()->getQSettings();

		QString qsGroup = getSettingsGroupKey(vmIdent);
		pQSettings->remove(qsGroup);
	}

	{
		QMutexLocker locker(&m_lockVmIdents);

		if ( ! m_mapVmIdents.contains(vmIdent) )
			return PRL_ERR_SUCCESS;

// Stop timer

		emit killVmTimerSignal(m_mapVmIdents.value(vmIdent).iTimerId);

// TODO: Check running task for this VM. Cancel it ?

// Unregister VM

		m_mapVmIdents.remove(vmIdent);
	}

	return finalizeUnregistration( vmIdent, pClient, bEditVmConfig );
}
PRL_RESULT Task_ChangeSID::save_config(SmartPtr<CVmConfiguration> &pVmConfig)
{
	PRL_RESULT ret;

	CDspLockedPointer< CVmDirectoryItem >
		pVmDirItem = CDspService::instance()->getVmDirManager()
		.getVmDirItemByUuid(getClient()->getVmDirectoryUuid(), getVmUuid());
	if (!pVmDirItem)
		return PRL_ERR_VM_UUID_NOT_FOUND;

	ret = CDspService::instance()->getVmConfigManager().saveConfig(pVmConfig,
			pVmDirItem->getVmHome(),
			getClient(),
			true,
			true);
	if (PRL_FAILED(ret))
	{
		WRITE_TRACE(DBG_FATAL, "Unable to save configuration of the VM to file %s. Reason: %ld: %s",
				pVmConfig->getOutFileName().toUtf8().data(),
				Prl::GetLastError(),
				QSTR2UTF8( Prl::GetLastErrorAsString())
			   );
		return ret;
	}
	return PRL_ERR_SUCCESS;
}
QString CDspDispConfigGuard::getDispUserByUuidAsString( const QString& userUuid )
{
	CDspLockedPointer<CDispUser> pUser = getDispUserByUuid( userUuid );
	QString sUserProfile;
	if (pUser.getPtr())
		sUserProfile = pUser->toString();
	return sUserProfile;
}
// check if addition vm state was changed and post event if changed
void CDspTaskHelper::checkVmAdditionState( bool bExcludeThisForSearch )
{
	if( !providedAdditionState() || !getClient() )
		return;

	if( getVmUuid().isEmpty() )
		return;

	VIRTUAL_MACHINE_ADDITION_STATE state =
				CDspVm::getVmAdditionState( getVmUuid(), getClient()->getVmDirectoryUuid(),
											bExcludeThisForSearch ? this : NULL );

	CDspLockedPointer<CDspVmStateSender>
		pLockedVmStateSender = CDspService::instance()->getVmStateSender();

	if( pLockedVmStateSender )
		pLockedVmStateSender->onVmAdditionStateChanged( state,
														getVmUuid(),
														getClient()->getVmDirectoryUuid() );
}
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;
}
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));
	}
}
void CDspVmAutoTaskManagerBase::timerEvent(QTimerEvent* te)
{
	if (!IsInitialized())
	{
		WRITE_TRACE( DBG_WARNING, "Timer event on unitialized %s manager", getManagerName() );
		return;
	}

// Looking for proper VM ident.

	bool bRestartTimer = false;
	TimerInfo timerInfo;
	CVmIdent vmIdent;
	{
		QMutexLocker locker(&m_lockVmIdents);

		QMap<CVmIdent, TimerInfo >::iterator it;
		for(it = m_mapVmIdents.begin(); it != m_mapVmIdents.end(); ++it)
		{
			timerInfo = it.value();
			if (timerInfo.iTimerId == te->timerId())
				break;
		}

		if ( it == m_mapVmIdents.end() || timerInfo.bTaskInUse)
			return;

		vmIdent = it.key();

		bRestartTimer = (timerInfo.iPeriod != timerInfo.iOriginalPeriod);

		if (bRestartTimer)
		{
			emit killVmTimerSignal(timerInfo.iTimerId);

			m_mapVmIdents.remove(vmIdent);
		}
	}

	if (bRestartTimer)
	{
		emit startVmTimerSignal(vmIdent, timerInfo.iOriginalPeriod, timerInfo.iOriginalPeriod);
	}

// Store timestamp
	{
		CDspLockedPointer<QSettings> pQSettings = CDspService::instance()->getQSettings();

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

		pQSettings->setValue(getSettingsKeyTimestamp(), QVariant(QDateTime::currentDateTime()));

		pQSettings->endGroup();
	}

// Get client

	QHash< IOSender::Handle, SmartPtr<CDspClient> > hashClients =
		CDspService::instance()->getClientManager().getSessionListByVm(
		vmIdent.second, vmIdent.first, CDspAccessManager::VmAccessRights::makeModeRWX() );
	if ( hashClients.empty() )
	{
		WRITE_TRACE(DBG_FATAL, "No clients connect to VM %s with required permissions",
								QSTR2UTF8(vmIdent.first) );
		return;
	}

// Start auto task

	if ( ! updateTaskState(vmIdent, true) )
		return;

	// Fake client
	SmartPtr<CDspClient> pClient( new CDspClient(IOSender::Handle()) );
	pClient->getAuthHelper().AuthUserBySelfProcessOwner();
	pClient->setVmDirectoryUuid(vmIdent.second);

	startTask( pClient, vmIdent );
}
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;
}
/* 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::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;
}
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;
}
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;
}