লগইনগুলি উপলভ্যতা গোষ্ঠীগুলিতে সিঙ্ক হচ্ছে না


13

অলওয়েভন গ্রুপে আমাদের 2 টি সার্ভার রয়েছে।

প্রতিটি সিঙ্ক্রোনাইজড ডাটাবেসের মধ্যে থাকা ব্যবহারকারী অ্যাকাউন্টগুলি উভয় সার্ভারে উপস্থিত থাকলেও ডাটাবেস উদাহরণ স্তরের লগইন কেবল একটি সার্ভারে উপস্থিত থাকে। যেমন DBINSTANCE-> সুরক্ষা-> লগইনগুলি একটি সার্ভারে অনুপস্থিত।

সুতরাং যখন একটি ব্যর্থতা আছে, আমি দ্বিতীয় সার্ভারে লগইন ব্যর্থতা পেয়েছি (যার সাথে সম্পর্কিত উদাহরণ স্তরের লগইন নেই)।

আমি কীভাবে এই সমস্যাটি কাটিয়ে উঠব? আমার কি একটি বিশেষ উপায়ে ব্যবহারকারীর অ্যাকাউন্ট সেট আপ করার কথা ছিল?


আমি সম্প্রতি এটির দিকেও নজর রাখতে শুরু করেছি, আমি আমার নিজস্বটি রোল করেছি এবং বর্তমানে এটি আমার ব্র্যান্ডের নতুন ব্লগে বর্ণনা করছি (বেশিরভাগ ক্ষেত্রে আমার নিজের সুবিধার জন্য আমি যখন এগিয়ে যাই এবং জিনিসগুলি ভুলে যাই তবে অন্যের পক্ষে যদি এটি আরও ভালভাবে সাহায্য করা হয়) জীবন -আর -দেব.ব্লগস্পট.কম.২০ /

আপনি স্কেলস্কিলস থেকে এসএসএমএস প্লাগইন ব্যবহার করতে পারেন উপলভ্যতা গ্রুপ
কিন শাহ

উত্তর:


15

আমার বোধগম্যতা হল আপনি যদি কনটেইনড ডেটাবেসগুলি ব্যবহার না করেন তবে আপনাকে অবশ্যই নিশ্চিত করতে হবে যে লগইনগুলি অন্য পরিস্থিতিতে ম্যানুয়ালি তৈরি হয়েছে created

মূলত এসকিউএলসোল্ডার-এর এই স্ক্রিপ্টের মতো , লগিনগুলি একটি ডেটাবেস মিররে স্থানান্তরিত হিসাবে পোস্ট করা , কৌশলটি করা উচিত।


আমরা পরের সপ্তাহে বা দু'বার '12 এ স্যুইচ করলে একবারে আমাদের বেশিরভাগ প্রোডাকশন '05 ডাটাবেসকে নতুন অন্তর্নির্মিত ফর্ম্যাটে রূপান্তরিত করতে প্রত্যাশা করছি। মাঝামাঝি সময়ে, আমি লগইন, চাকুরী ইত্যাদি অনুলিপি করার জন্য ইডেরার সরঞ্জামগুলি ব্যবহার করছি instance
ম্যাক্স ভার্নন

চিহ্নটি সঠিক, আপনাকে অবশ্যই অন্তর্ভুক্ত ডাটাবেসগুলি ব্যবহার করতে হবে বা সমস্ত দৃষ্টান্তে একই এসআইডি ব্যবহার করে ক্লাস্টারের সমস্ত দস্তাবেজে ম্যানুয়ালি লগইনগুলি অনুলিপি করতে হবে।
mrdenny

মনে রাখবেন যে আমি আয়নার চেয়ে নয়, এলিভারঅন সম্পর্কে জিজ্ঞাসা করছি। আমি স্ক্রিপ্টটি চেষ্টা করেছি, তবে সিস.সভার্স টেবিলটিতে কেবলমাত্র স্থানীয় সার্ভার রয়েছে তাই আমি সঞ্চিত ক্রিয়াকলাপটি চালানোর সময় আমি নিম্নলিখিত ত্রুটিটি পাই: Msg 7202, Level 11, State 2, Line 1 Could not find server 'otherserver' in sys.servers. Verify that the correct server name was specified. If necessary, execute the stored procedure sp_addlinkedserver to add the server to sys.servers.
জন

আমি এটি খুঁজে পেয়েছি এবং এভারএলওয়ের জন্য উপযুক্ত একটি নতুন উত্তর পোস্ট করেছি।
জন

@ জনহিউজ এই স্ক্রিপ্টটি সর্বদা জন্য উপযুক্ত। তবুও, ত্রুটি বার্তা দ্বারা নির্দেশিত হিসাবে, উদাহরণগুলির মধ্যে একটি লিঙ্কযুক্ত সার্ভার তৈরি করা দরকার।
মার্ক স্টোরী-স্মিথ

7

আপনার অবশ্যই একটি অন্তর্ভুক্ত ডেটাবেস ব্যবহার করা উচিত, অথবা আপনাকে অবশ্যই অন্যান্য পাসওয়ার্ড (গুলি) এ একই পাসওয়ার্ড হ্যাশ এবং এসআইডি দিয়ে ব্যবহারকারীদের পুনরায় তৈরি করতে হবে।

এটি করার জন্য একটি স্ক্রিপ্ট মাইক্রোসফ্ট সরবরাহ করেছে: এসকিউএল সার্ভারের উদাহরণগুলির মধ্যে লগইন এবং পাসওয়ার্ড কীভাবে স্থানান্তর করতে হয়

মার্কের সমাধানটি আংশিকভাবে সঠিক ছিল তবে তাঁর প্রস্তাবিত সমাধানটি মিররড ডেটাবেসের জন্য ছিল, যেমন ওভারএল-এর বিপরীতে যা প্রশ্নগুলি জিজ্ঞাসা করে।


2
মিররড ডাটাবেসের সমাধান কীভাবে সহজলভ্যতা গ্রুপগুলির সমাধানের চেয়ে আলাদা (দ্রষ্টব্য: অলএলওন একটি গুচ্ছ প্রযুক্তির জন্য একটি বিপণন লেবেল, কোনও বৈশিষ্ট্য নয়)? কোনও ব্লগ পোস্টের শিরোনামের সত্যতা পরিবর্তন হয় না যে এটি অনুপস্থিত লগইনগুলি পুনরুদ্ধার করছে - যা আপনি মিররিং, প্রাপ্যতা গ্রুপ, লগ শিপিং, ম্যানুয়াল ব্যাকআপ / পুনরুদ্ধার ইত্যাদি ব্যবহার করছেন কিনা এর সাথে কিছুই করার নেই which
অ্যারন বারট্র্যান্ড

দুর্ভাগ্যক্রমে, আমি সর্বদা AD অ্যাকাউন্টগুলি ব্যবহার করতে পারি না। আমরা পাসওয়ার্ডগুলির সাথে তুলনা করার একটি উপায় নিয়ে লড়াই করছি। আমরা কী ধরে নিচ্ছি না যে পাসওয়ার্ডগুলি মেলে না, প্রতিলিপি সার্ভারগুলির মধ্যে ব্যর্থতা ব্যর্থ হবে?

1

আমি দীর্ঘ সময় পরে পোস্টে সাড়া দিচ্ছি তবে এটি অনুরূপ সমস্যা সহ অন্য কাউকে সহায়তা করতে পারে। পাওয়ারশেল প্রাথমিক প্রতিলিপি থেকে মাধ্যমিক প্রতিরূপগুলিতে লগইনগুলি অনুলিপি করতে ব্যবহার করা যেতে পারে। বিশদগুলি এখানে পাওয়া যাবে https://maq.guru/synchronizing-sql-server-logins-in-an-always-on- उपलब्धি-group/

সম্পূর্ণ প্রকাশ: উপরের সাইটটির মালিক আমার।

পাওয়ারশেল লিপি:

$Conn=New-Object System.Data.SqlClient.SQLConnection
$QueryTimeout = 120
$ConnectionTimeout = 30

###########################################################
# Execute Query function 
###########################################################
Function executequery($Query, $QueryTimeout, $ServerName)
{
    $Datatable = New-Object System.Data.DataTable
    $ConnectionString = "Server={0};Database={1};Integrated Security=True;Connect Timeout={2}" -f $ServerName,$Database,$ConnectionTimeout
    $Conn.ConnectionString=$ConnectionString
    $Cmd=New-Object system.Data.SqlClient.SqlCommand($Query,$Conn)
    $Cmd.CommandTimeout=$QueryTimeout

            do
                {   
                    $Conn.Open()
                    Start-Sleep -Seconds 2
                }while ($Conn.State -ne 'Open')

            $Reader = $cmd.ExecuteReader()
            $Datatable.Load($Reader)
            $Conn.Close()
            return $Datatable    
}


###########################################################
# Create spHexaDecimal Stored Procedure
###########################################################

Function CreatespHexaDecimal ($ServerName)
    {
    $Query='USE [master];
                GO
                SET ANSI_NULLS ON;
                GO
                SET QUOTED_IDENTIFIER ON;
                GO
                CREATE PROCEDURE [dbo].[spHexaDecimal]
                (
                    @BinValue VARBINARY(256)
                    , @HexValue VARCHAR(514) OUTPUT
                )
                AS

                DECLARE @CharValue VARCHAR(514)
                DECLARE @i INT
                DECLARE @Length INT
                DECLARE @HexString CHAR(16)

                SET @CharValue = ''0x''
                SET @i = 1
                SET @Length = DATALENGTH(@BinValue)
                SET @HexString = ''0123456789ABCDEF''

                WHILE (@i <= @Length)
                BEGIN

                    DECLARE @TempInt INT
                    DECLARE @FirstInt INT
                    DECLARE @SecondInt INT

                    SET @TempInt = CONVERT(INT, SUBSTRING(@BinValue, @i, 1))
                    SET @FirstInt = FLOOR(@TempInt/16)
                    SET @SecondInt = @TempInt - (@FirstInt * 16)
                    SET @CharValue = @CharValue 
                                        + SUBSTRING(@HexString, @FirstInt + 1, 1)
                                        + SUBSTRING(@HexString, @SecondInt + 1, 1)

                    SET @i = @i + 1

                END --WHILE (@i <= @Length)

                SET @HexValue = @CharValue'

                Invoke-Sqlcmd -Query $Query -ServerInstance $ServerName
    }


###########################################################
# CheckStroedProc 
###########################################################

Function CheckStoredProc ($Server)
{
    $Query= 'SELECT 1 AS ExistCheck
             FROM   sysobjects 
             WHERE  id = object_id(N''[dbo].[spHexaDecimal]'') 
                 AND OBJECTPROPERTY(id, N''IsProcedure'') = 1 '

    $Result=executequery $Query $QueryTimeout $Server
    $Exist=$Result | SELECT -ExpandProperty ExistCheck
    IF ($Exist -ne 1)
        {
            CreatespHexaDecimal -ServerName $Server
        }
}

###########################################################
# Get Login Script
###########################################################

Function Get-Script ($Server)
{

$Query='DECLARE @TempTable TABLE
(Script NVARCHAR(MAX))
DECLARE @Login NVARCHAR (MAX)
DECLARE CURLOGIN CURSOR FOR
SELECT name 
FROM sys.server_principals
WHERE CONVERT(VARCHAR(24),create_date,103) = CONVERT(VARCHAR(24),GETDATE(),103)
    OR CONVERT(VARCHAR(24),modify_date,103) = CONVERT(VARCHAR(24),GETDATE(),103)

OPEN CURLOGIN
    FETCH NEXT FROM CURLOGIN INTO @Login

WHILE @@FETCH_STATUS = 0
BEGIN
    SET NOCOUNT ON
    DECLARE @Script NVARCHAR (MAX)
    DECLARE @LoginName VARCHAR(500)= @Login
    DECLARE @LoginSID VARBINARY(85)
    DECLARE @SID_String VARCHAR(514)
    DECLARE @LoginPWD VARBINARY(256)
    DECLARE @PWD_String VARCHAR(514)
    DECLARE @LoginType CHAR(1)
    DECLARE @is_disabled BIT
    DECLARE @default_database_name SYSNAME
    DECLARE @default_language_name SYSNAME
    DECLARE @is_policy_checked BIT
    DECLARE @is_expiration_checked BIT
    DECLARE @createdDateTime DATETIME



    SELECT @LoginSID = P.[sid]
        , @LoginType = P.[type]
        , @is_disabled = P.is_disabled 
        , @default_database_name = P.default_database_name 
        , @default_language_name = P.default_language_name 
        , @createdDateTime = P.create_date 
    FROM sys.server_principals P
    WHERE P.name = @LoginName

    /** Some Output **/
    SET @Script = ''''




    --If the login is a SQL Login, then do a lot of stuff...
    IF @LoginType = ''S''
    BEGIN

        SET @LoginPWD = CAST(LOGINPROPERTY(@LoginName, ''PasswordHash'') AS VARBINARY(256))

        EXEC spHexaDecimal @LoginPWD, @PWD_String OUT   
        EXEC spHexaDecimal @LoginSID, @SID_String OUT

        SELECT @is_policy_checked = S.is_policy_checked
            , @is_expiration_checked = S.is_expiration_checked
        FROM sys.sql_logins S

        /** Create Script **/
        SET @Script = @Script + CHAR(13) + CHAR(13)
                        + ''IF EXISTS (SELECT name FROM sys.server_principals WHERE name= ''''''+ @LoginName + '''''') '' 
                        + CHAR(13) + '' BEGIN ''
                        + CHAR(13) + CHAR(9) + '' ALTER LOGIN '' + QUOTENAME(@LoginName)
                        + CHAR(13) + CHAR(9) + ''WITH PASSWORD = '' + @PWD_String + '' HASHED''
                        + CHAR(13) + CHAR(9) + '', DEFAULT_DATABASE = ['' + @default_database_name + '']''
                        + CHAR(13) + CHAR(9) + '', DEFAULT_LANGUAGE = ['' + @default_language_name + '']''
                        + CHAR(13) + CHAR(9) + '', CHECK_POLICY '' + CASE WHEN @is_policy_checked = 0 THEN ''=OFF'' ELSE ''=ON'' END
                        + CHAR(13) + CHAR(9) + '', CHECK_EXPIRATION '' + CASE WHEN @is_expiration_checked = 0 THEN ''=OFF'' ELSE ''=ON'' END
                        + CHAR(13) + '' END ''
                        + CHAR(13) + ''ELSE''
                        + CHAR(13) + '' BEGIN ''
                        + CHAR(13) + CHAR(9) + '' CREATE LOGIN '' + QUOTENAME(@LoginName)
                        + CHAR(13) + CHAR(9) + ''WITH PASSWORD = '' + @PWD_String + '' HASHED''
                        + CHAR(13) + CHAR(9) + '', SID = '' + @SID_String
                        + CHAR(13) + CHAR(9) + '', DEFAULT_DATABASE = ['' + @default_database_name + '']''
                        + CHAR(13) + CHAR(9) + '', DEFAULT_LANGUAGE = ['' + @default_language_name + '']''
                        + CHAR(13) + CHAR(9) + '', CHECK_POLICY '' + CASE WHEN @is_policy_checked = 0 THEN ''=OFF'' ELSE ''=ON'' END
                        + CHAR(13) + CHAR(9) + '', CHECK_EXPIRATION '' + CASE WHEN @is_expiration_checked = 0 THEN ''=OFF'' ELSE ''=ON'' END
                        + CHAR(13) + '' END ''

        SET @Script = @Script + CHAR(13) + CHAR(13)
                        + '' ALTER LOGIN ['' + @LoginName + '']''
                        + CHAR(13) + CHAR(9) + ''WITH DEFAULT_DATABASE = ['' + @default_database_name + '']''
                        + CHAR(13) + CHAR(9) + '', DEFAULT_LANGUAGE = ['' + @default_language_name + '']''

    END
    ELSE
    BEGIN

        --The login is a NT login (or group).
        SET @Script = @Script + CHAR(13) + CHAR(13)
                        + ''IF NOT EXISTS (SELECT name FROM sys.server_principals WHERE name= ''''''+ @LoginName + '''''') '' 
                        + CHAR(13) + '' BEGIN ''
                        + CHAR(13) + CHAR(9) + '' CREATE LOGIN '' + QUOTENAME(@LoginName) + '' FROM WINDOWS''
                        + CHAR(13) + CHAR(9) + ''WITH DEFAULT_DATABASE = ['' + @default_database_name + '']''
                        + CHAR(13) + '' END ''
    END

    /******************************************************************************************/
    --This section deals with the Server Roles that belong to that login...
    /******************************************************************************************/

    DECLARE @ServerRoles TABLE
        (
        ServerRole SYSNAME
        , MemberName SYSNAME
        , MemberSID VARBINARY(85)
        )

    INSERT INTO @ServerRoles EXEC sp_helpsrvrolemember

    --Remove all Roles
    SET @Script = @Script + CHAR(13)
    SET @Script = @Script 
                            + CHAR(13) + ''EXEC sp_dropsrvrolemember '' + QUOTENAME(@LoginName, '''''''') + '', '' + ''''''sysadmin''''''
                            + CHAR(13) + ''EXEC sp_dropsrvrolemember '' + QUOTENAME(@LoginName, '''''''') + '', '' + ''''''securityadmin''''''
                            + CHAR(13) + ''EXEC sp_dropsrvrolemember '' + QUOTENAME(@LoginName, '''''''') + '', '' + ''''''serveradmin'''''' 
                            + CHAR(13) + ''EXEC sp_dropsrvrolemember '' + QUOTENAME(@LoginName, '''''''') + '', '' + ''''''setupadmin'''''' 
                            + CHAR(13) + ''EXEC sp_dropsrvrolemember '' + QUOTENAME(@LoginName, '''''''') + '', '' + ''''''processadmin''''''
                            + CHAR(13) + ''EXEC sp_dropsrvrolemember '' + QUOTENAME(@LoginName, '''''''') + '', '' + ''''''diskadmin'''''' 
                            + CHAR(13) + ''EXEC sp_dropsrvrolemember '' + QUOTENAME(@LoginName, '''''''') + '', '' + ''''''dbcreator'''''' 
                            + CHAR(13) + ''EXEC sp_dropsrvrolemember '' + QUOTENAME(@LoginName, '''''''') + '', '' + ''''''bulkadmin'''''' 

    /** Output to script... **/
    --SET @Script = @Script + CHAR(13) + CHAR(13)

    --Test if there are any server roles for this login...
    IF EXISTS(SELECT 1 FROM @ServerRoles WHERE MemberName = @LoginName)
    BEGIN

        SET @Script = @Script + CHAR(13)

        DECLARE @ServerRole SYSNAME
        DECLARE curRoles CURSOR LOCAL STATIC FORWARD_ONLY

        FOR SELECT ServerRole 
            FROM @ServerRoles
            WHERE MemberName = @LoginName

        OPEN curRoles

        FETCH NEXT FROM curRoles
        INTO @ServerRole

        WHILE @@FETCH_STATUS = 0
        BEGIN

            /** Output to Script **/
            SET @Script = @Script 
                            + CHAR(13) + ''EXEC sp_addsrvrolemember '' + QUOTENAME(@LoginName, '''''''') + '', '' + QUOTENAME(@ServerRole, '''''''')

            FETCH NEXT FROM curRoles
            INTO @ServerRole

        END

        --Cleanup.
        CLOSE curRoles
        DEALLOCATE curRoles

    END
    INSERT INTO @TempTable
    VALUES(@Script)

    FETCH NEXT FROM CURLOGIN INTO @Login
END
CLOSE CURLOGIN;
DEALLOCATE CURLOGIN;
SELECT Script FROM @TempTable'

$Result=executequery $Query $QueryTimeout $Server

If($Result -eq $null)
    {
        break
    }
Else
    {
        [Void][System.IO.Directory]::CreateDirectory("C:\temp")
        $Path = "C:\temp"
        $Acl = (Get-Item $Path).GetAccessControl('Access')
        $Username = Get-WmiObject win32_service | Where name -EQ 'SQLSERVERAGENT' | Select -ExpandProperty StartName
        $Ar = New-Object System.Security.AccessControl.FileSystemAccessRule($Username, 'Full', 'ContainerInherit,ObjectInherit', 'None', 'Allow')
        $Acl.SetAccessRule($Ar)
        Set-Acl -path $Path -AclObject $Acl
        $Result | select -ExpandProperty Script | Out-File C:\temp\Script.txt
    }
}


###########################################################
# SCRIPT BODY 
###########################################################

$Query= "SELECT ISNULL(SERVERPROPERTY ('InstanceName'), 'DEFAULT') InstanceName 
            , name AGName
            , replica_server_name Replica
            , role_desc 
            FROM sys.dm_hadr_availability_replica_states hars 
            INNER JOIN sys.availability_groups ag ON ag.group_id = hars.group_id 
            INNER JOIN sys.availability_replicas ar ON ar.replica_id = hars.replica_id
            WHERE role_desc = 'PRIMARY'
            ORDER BY role_desc asc"
Write-Host "Is this Primary Replica?"
$Result=executequery $Query $QueryTimeout $PrimaryReplica
If ($Result -eq $null)
    {
        Write-Host "No, it's not."
        break
    }
Else
    {
        Write-Host "Yes, it is."
        $PrimaryReplica= $Result | select -ExpandProperty Replica
        Write-Host "Check for prerequisite, if not present deploy it."
        CheckStoredProc -Server $PrimaryReplica
        Write-Host "Get script for new/modifies login(s)."
        Get-Script -Server $PrimaryReplica

        $Query= "SELECT ISNULL(SERVERPROPERTY ('InstanceName'), 'DEFAULT') InstanceName 
                    , name AGName
                    , replica_server_name Replica
                    , role_desc 
                    FROM sys.dm_hadr_availability_replica_states hars 
                    INNER JOIN sys.availability_groups ag ON ag.group_id = hars.group_id 
                    INNER JOIN sys.availability_replicas ar ON ar.replica_id = hars.replica_id
                    WHERE role_desc = 'SECONDARY'
                    ORDER BY role_desc asc"

        $Result=executequery $Query $QueryTimeout $PrimaryReplica
        $SecondaryReplicas= $Result | select -ExpandProperty Replica
        $Query= Get-Content -Path 'C:\temp\Script.txt' | Out-String
        ForEach($SecondaryReplica in $SecondaryReplicas)
            {
                Invoke-Sqlcmd -Query $Query -ServerInstance $SecondaryReplica
                Write-Host "Successfully copied login(s) to $SecondaryReplica"
            }
        Remove-Item C:\temp\Script.txt
    }

2
ধন্যবাদ মুহাম্মদ, আপনি কি লিঙ্কটির কিছু বিষয়বস্তু অন্তর্ভুক্ত করতে পারেন? লিঙ্কটি মারা গেলে আপনার প্রশ্নটি অন্যথায় অনেক কম দরকারী হয়ে উঠবে!
লোলিডিবিএ

@ ললিডিবিএ, আমি স্ক্রিপ্টটি এখানে রাখার চেষ্টা করেছি তবে দুর্ভাগ্যক্রমে এটি অনেক দীর্ঘ :( এই ওয়েবসাইটটির মালিক হওয়ার সাথে লিঙ্কটি মারা যাবে না
মুহাম্মদ

স্ক্রিপ্টটি খুব দীর্ঘ নয়। আমি এটি আপনার জন্য যোগ করব। এবং সেই ক্ষেত্রে, আপনার নিজের লিঙ্কগুলি পোস্ট করার সময় আপনার অনুমোদিততা প্রকাশ করতে হবে ।
লোলিডিবিএ

ক্ষমা চেয়ে নিলাম @ লুলিডিবিএ, আমি প্রকাশ সম্পর্কে সচেতন ছিলাম না। আমি এখানে স্ক্রিপ্টটি মন্তব্য বিভাগে রাখার চেষ্টা করেছি তবে এটি নির্দিষ্ট সংখ্যক চরিত্রের মধ্যেই সীমাবদ্ধ। আমি সম্পূর্ণ স্ক্রিপ্ট যুক্ত করেছি। ধন্যবাদ
মুহাম্মদ

এটি বেশ লজ্জাজনক যে সার্ভার-স্তরের সিঙ্কটি এজি-র অংশ নয়। আপনার উত্তরটি এমএসকে কল করে নিবন্ধটির জন্য একটি উত্সাহ পেয়েছে।
youcantryreachingme

-1

আপনাকে অবশ্যই উইন্ডোজ ডোমেন লগইনগুলি ব্যবহার করতে হবে এবং প্রতিটি মুহূর্তে সেগুলি তৈরি করতে হবে, এসআইডি যেমন সক্রিয় ডিরেক্টরি দ্বারা পরিচালিত হয় আপনি প্রাথমিক প্রতিরূপে লগইন উপস্থিত থাকলে প্রাপ্যতা গোষ্ঠীর সমস্ত প্রতিরূপ সদস্যদের অ্যাক্সেস করতে সক্ষম হবেন। অন্য একটি বিকল্প আপনাকে অবশ্যই একটি শংসাপত্র ব্যবহার করতে হবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.