public async Task RemoveActivation(ClusterIdentity clusterIdentity, PID pid, CancellationToken ct)
        {
            Logger.LogDebug("Removing activation: {ClusterIdentity} {@PID}", clusterIdentity, pid);

            var key = GetKey(clusterIdentity);
            await _asyncSemaphore.WaitAsync(() => _pids.DeleteManyAsync(p => p.Key == key && p.UniqueIdentity == pid.Id, ct));
        }
예제 #2
0
        public async Task<SpawnLock?> TryAcquireLock(ClusterIdentity clusterIdentity, CancellationToken ct)
        {
            var requestId = Guid.NewGuid().ToString("N");
            var hasLock = await _asyncSemaphore.WaitAsync(() => TryAcquireLockAsync(clusterIdentity, requestId)).ConfigureAwait(false);

            return hasLock ? new SpawnLock(requestId, clusterIdentity) : null;
        }
예제 #3
0
        public async Task Setup()
        {
            var echoProps = Props.FromFunc(ctx => {
                if (ctx.Sender is not null)
                {
                    ctx.Respond(ctx.Message !);
                }
                return(Task.CompletedTask);
            }
                                           );

            if (RequestDeduplication)
            {
                echoProps = echoProps.WithClusterRequestDeduplication(TimeSpan.FromSeconds(30));
            }

            var echoKind = new ClusterKind(Kind, echoProps);

            if (LocalAffinity)
            {
                echoKind.WithLocalAffinityRelocationStrategy();
            }

            var sys = new ActorSystem(new ActorSystemConfig())
                      .WithRemote(GrpcNetRemoteConfig.BindToLocalhost(9090))
                      .WithCluster(ClusterConfig().WithClusterKind(echoKind));

            _cluster = sys.Cluster();
            await _cluster.StartMemberAsync();

            _id = ClusterIdentity.Create("1", Kind);
            await _cluster.RequestAsync <int>(_id.Identity, _id.Kind, 1, CancellationToken.None);
        }
예제 #4
0
        public async Task PurgesPidCacheOnNullResponse()
        {
            var system = new ActorSystem();

            system.Metrics.Register(new ClusterMetrics(system.Metrics));
            var props    = Props.FromProducer(() => new EchoActor());
            var deadPid  = system.Root.SpawnNamed(props, "stopped");
            var alivePid = system.Root.SpawnNamed(props, "alive");
            await system.Root.StopAsync(deadPid).ConfigureAwait(false);

            var dummyIdentityLookup = new DummyIdentityLookup(alivePid);
            var pidCache            = new PidCache();

            var logger          = Log.CreateLogger("dummylog");
            var clusterIdentity = new ClusterIdentity {
                Identity = "identity", Kind = "kind"
            };

            pidCache.TryAdd(clusterIdentity, deadPid);
            var requestAsyncStrategy = new DefaultClusterContext(dummyIdentityLookup, pidCache, new ClusterContextConfig(), system.Shutdown);

            var res = await requestAsyncStrategy.RequestAsync <Pong>(clusterIdentity, new Ping { Message = "msg" }, system.Root,
                                                                     new CancellationTokenSource(6000).Token
                                                                     );

            res !.Message.Should().Be("msg");
            var foundInCache = pidCache.TryGet(clusterIdentity, out var pidInCache);

            foundInCache.Should().BeTrue();
            pidInCache.Should().BeEquivalentTo(alivePid);
        }
예제 #5
0
 public async Task<StoredActivation?> TryGetExistingActivation(
     ClusterIdentity clusterIdentity,
     CancellationToken ct
 )
 {
     var activationStatus = await LookupKey(GetDb(), IdKey(clusterIdentity)).ConfigureAwait(false);
     return activationStatus?.Activation;
 }
        public async Task <SpawnLock?> TryAcquireLock(
            ClusterIdentity clusterIdentity,
            CancellationToken ct
            )
        {
            var requestId = Guid.NewGuid().ToString();
            var hasLock   = await TryAcquireLockAsync(clusterIdentity, requestId, ct);

            return(hasLock ? new SpawnLock(requestId, clusterIdentity) : null);
        }
        public Task RemovePidAsync(ClusterIdentity clusterIdentity, PID pid, CancellationToken ct)
        {
            var activationTerminated = new ActivationTerminated
            {
                Pid             = pid,
                ClusterIdentity = clusterIdentity,
            };

            _cluster.MemberList.BroadcastEvent(activationTerminated);

            return(Task.CompletedTask);
        }
        public async Task <StoredActivation?> TryGetExistingActivation(
            ClusterIdentity clusterIdentity,
            CancellationToken ct
            )
        {
            var pidLookup = await LookupKey(GetKey(clusterIdentity), ct);

            return(pidLookup?.Address == null || pidLookup?.UniqueIdentity == null
                ? null
                : new StoredActivation(pidLookup.MemberId !,
                                       PID.FromAddress(pidLookup.Address, pidLookup.UniqueIdentity)
                                       ));
        }
 public AzureHDInsightClusterIdentity(ClusterIdentity clusterIdentity)
 {
     PrincipalId            = clusterIdentity?.PrincipalId;
     TenantId               = clusterIdentity?.TenantId;
     Type                   = clusterIdentity?.Type;
     UserAssignedIdentities = clusterIdentity?.UserAssignedIdentities != null ? new Dictionary <string, AzureHDInsightUserAssignedIdentity>() : null;
     if (UserAssignedIdentities != null)
     {
         foreach (var entry in clusterIdentity.UserAssignedIdentities)
         {
             UserAssignedIdentities.Add(entry.Key, new AzureHDInsightUserAssignedIdentity(entry.Value));
         }
     }
 }
예제 #10
0
        public void CannotStoreWithoutLock()
        {
            var timeout   = new CancellationTokenSource(1000).Token;
            var activator = GetFakeActivator();
            var identity  = new ClusterIdentity {
                Kind = "thing", Identity = NextId().ToString()
            };
            var spawnLock = new SpawnLock("not-a-lock", identity);
            var pid       = Activate(activator, identity);

            _storage.Invoking(storage =>
                              storage.StoreActivation(activator.Id, spawnLock, pid, timeout)
                              ).Should().Throw <LockNotFoundException>();
        }
        internal Action <MessageEnvelope> ForActor(ClusterIdentity identity, PID activation)
        {
            var activeRemotes = new BitArray(16);

            return(envelope => {
                if (envelope.Message is Stopped)
                {
                    Invalidate(identity, activation, activeRemotes);
                }
                else if (IsRemote(envelope.Sender))
                {
                    AddRemote(envelope.Sender !, activeRemotes);
                }
            });
        }
예제 #12
0
        private Task<bool> TryAcquireLockAsync(
            ClusterIdentity clusterIdentity,
            string requestId
        )
        {
            var key = IdKey(clusterIdentity);

            var db = GetDb();
            var transaction = db.CreateTransaction();

            transaction.AddCondition(Condition.KeyNotExists(key));
            transaction.HashSetAsync(key, LockId, requestId);
            transaction.KeyExpireAsync(key, _maxLockTime);

            return transaction.ExecuteAsync();
        }
        public async Task <StoredActivation?> WaitForActivation(
            ClusterIdentity clusterIdentity,
            CancellationToken ct
            )
        {
            var key             = GetKey(clusterIdentity);
            var pidLookupEntity = await LookupKey(key, ct);

            var lockId = pidLookupEntity?.LockedBy;

            if (lockId != null)
            {
                //There is an active lock on the pid, spin wait
                var i = 0;
                do
                {
                    await Task.Delay(20 *i, ct);
                }while ((pidLookupEntity = await LookupKey(key, ct))?.LockedBy == lockId && ++i < 10);
            }

            //the lookup entity was lost, stale lock maybe?
            if (pidLookupEntity == null)
            {
                return(null);
            }

            //lookup was unlocked, return this pid
            if (pidLookupEntity.LockedBy == null)
            {
                return(new StoredActivation(pidLookupEntity.MemberId !,
                                            PID.FromAddress(pidLookupEntity.Address !, pidLookupEntity.UniqueIdentity !)
                                            ));
            }

            //Still locked but not by the same request that originally locked it, so not stale
            if (pidLookupEntity.LockedBy != lockId)
            {
                return(null);
            }

            //Stale lock. just delete it and let cluster retry
            // _logger.LogDebug($"Stale lock: {pidLookupEntity.Key}");
            await RemoveLock(new SpawnLock(lockId !, clusterIdentity), CancellationToken.None);

            return(null);
        }
예제 #14
0
        public async Task GlobalLockActivatesOnceOnly()
        {
            var timeout  = new CancellationTokenSource(1000).Token;
            var identity = new ClusterIdentity {
                Kind = "thing", Identity = NextId().ToString()
            };
            const int attempts = 10;

            var locks = await Task.WhenAll(Enumerable.Range(1, attempts)
                                           .Select(i => _storage.TryAcquireLock(identity, timeout))
                                           );

            var successFullLock = locks.Where(it => it != null).ToList();

            successFullLock.Should().HaveCount(1);
            successFullLock.Single() !.ClusterIdentity.Should().BeEquivalentTo(identity);
        }
예제 #15
0
        public async Task RemovesLockIfStale()
        {
            var timeout  = new CancellationTokenSource(10000).Token;
            var identity = new ClusterIdentity {
                Kind = "thing", Identity = NextId().ToString()
            };
            await _storage.TryAcquireLock(identity, timeout);

            var activation = await _storage.WaitForActivation(identity, timeout);

            var spawnLock = await _storage.TryAcquireLock(identity, timeout);

            activation.Should().BeNull("We did not activate it");
            spawnLock.Should().NotBeNull(
                "When an activation did not occur, the storage implementation should discard the lock"
                );
        }
        private void Invalidate(ClusterIdentity identity, PID activation, BitArray activeRemotes)
        {
            var message = new ActivationTerminated
            {
                ClusterIdentity = identity,
                Pid             = activation
            };
            var remotesToInvalidate = Cluster.MemberList.GetAllMembers()
                                      .Select(m => Cluster.MemberList.GetMetaMember(m.Id))
                                      .Where(m => activeRemotes.Length > m.Index && activeRemotes[m.Index])
                                      .Select(m => m.Member.Address);

            foreach (var address in remotesToInvalidate)
            {
                Cluster.System.Root.Send(PID.FromAddress(address, ActorName), message);
            }
        }
예제 #17
0
        public async Task CanDeleteSpawnLocks()
        {
            var timeout  = new CancellationTokenSource(1000).Token;
            var identity = new ClusterIdentity {
                Kind = "thing", Identity = NextId().ToString()
            };

            var spawnLock = await _storage.TryAcquireLock(identity, timeout);

            spawnLock.Should().NotBeNull();

            await _storage.RemoveLock(spawnLock !, timeout);

            var secondLock = await _storage.TryAcquireLock(identity, timeout);

            secondLock.Should().NotBeNull("The initial lock should be cleared, and a second lock can be acquired.");
        }
        public async Task <PID?> GetAsync(ClusterIdentity clusterIdentity, CancellationToken ct)
        {
            ct = CancellationTokens.WithTimeout(_getPidTimeout);
            //Get address to node owning this ID
            var identityOwner = _partitionManager.Selector.GetIdentityOwner(clusterIdentity.Identity);

            Logger.LogDebug("Identity belongs to {address}", identityOwner);
            if (string.IsNullOrEmpty(identityOwner))
            {
                return(null);
            }

            var remotePid = PartitionManager.RemotePartitionIdentityActor(identityOwner);

            var req = new ActivationRequest
            {
                ClusterIdentity = clusterIdentity
            };

            Logger.LogDebug("Requesting remote PID from {Partition}:{Remote} {@Request}", identityOwner, remotePid, req
                            );

            try
            {
                var resp = await _cluster.System.Root.RequestAsync <ActivationResponse>(remotePid, req, ct);

                return(resp.Pid);
            }
            //TODO: decide if we throw or return null
            catch (DeadLetterException)
            {
                Logger.LogInformation("Remote PID request deadletter {@Request}, identity Owner {Owner}", req, identityOwner);
                return(null);
            }
            catch (TimeoutException)
            {
                Logger.LogInformation("Remote PID request timeout {@Request}, identity Owner {Owner}", req, identityOwner);
                return(null);
            }
            catch (Exception e)
            {
                Logger.LogError(e, "Error occured requesting remote PID {@Request}, identity Owner {Owner}", req, identityOwner);
                return(null);
            }
        }
예제 #19
0
        public Task RemoveActivation(ClusterIdentity clusterIdentity, PID pid, CancellationToken ct)
        {
            Logger.LogDebug("Removing activation: {ClusterIdentity} {@PID}", clusterIdentity, pid);

            const string removePid = "local pidEntry = redis.call('HMGET', KEYS[1], 'pid', 'adr', 'mid');\n" +
                                     "if pidEntry[1]~=ARGV[1] or pidEntry[2]~=ARGV[2] then return 0 end;\n" + // id / address matches
                                     "local memberKey = ARGV[3] .. pidEntry[3];\n" +
                                     "redis.call('SREM', memberKey, KEYS[1] .. '');" +
                                     "return redis.call('DEL', KEYS[1]);";

            var key = IdKey(clusterIdentity);
            return _asyncSemaphore.WaitAsync(()
                    => {
                    return GetDb().ScriptEvaluateAsync(removePid, new[] {key}, new RedisValue[] {pid.Id, pid.Address, _memberKey.ToString()}
                    );
                }
            );
        }
        private async Task <bool> TryAcquireLockAsync(
            ClusterIdentity clusterIdentity,
            string requestId,
            CancellationToken ct
            )
        {
            var key        = GetKey(clusterIdentity);
            var lockEntity = new PidLookupEntity
            {
                Address  = null,
                Identity = clusterIdentity.Identity,
                Key      = key,
                Kind     = clusterIdentity.Kind,
                LockedBy = requestId,
                Revision = 1,
                MemberId = null
            };

            try
            {
                //be 100% sure own the lock here
                await _asyncSemaphore.WaitAsync(() => _pids.InsertOneAsync(lockEntity, new InsertOneOptions(), ct));

                Logger.LogDebug("Got lock on first try for {ClusterIdentity}", clusterIdentity);
                return(true);
            }
            catch (MongoWriteException)
            {
                var l = await _asyncSemaphore.WaitAsync(() => _pids.ReplaceOneAsync(x => x.Key == key && x.LockedBy == null && x.Revision == 0,
                                                                                    lockEntity,
                                                                                    new ReplaceOptions
                {
                    IsUpsert = false
                }, ct
                                                                                    )
                                                        );

                //if l.MatchCount == 1, then one document was updated by us, and we should own the lock, no?
                var gotLock = l.IsAcknowledged && l.ModifiedCount == 1;
                Logger.LogDebug("Did {Got}get lock on second try for {ClusterIdentity}", gotLock ? "" : "not ", clusterIdentity);
                return(gotLock);
            }
        }
예제 #21
0
        /// <summary>
        /// Create cluster create parameters for ADLS Gen2 relevant tests
        /// </summary>
        /// <param name="commonData"></param>
        /// <param name="storageAccountName"></param>
        /// <param name="storageResourceId"></param>
        /// <param name="msiResourceId"></param>
        /// <param name="createParams"></param>
        /// <returns></returns>
        public static ClusterCreateParametersExtended PrepareClusterCreateParamsForADLSv2(
            this CommonTestFixture commonData,
            string storageAccountName,
            string storageResourceId,
            string msiResourceId,
            ClusterCreateParametersExtended createParams = null)
        {
            var  createParamsForADLSv2 = createParams ?? commonData.PrepareClusterCreateParams();
            bool isDefault             = !createParamsForADLSv2.Properties.StorageProfile.Storageaccounts.Any();

            createParamsForADLSv2.Properties.StorageProfile.Storageaccounts.Add(
                new HDInsightStorageAccount
            {
                Name          = storageAccountName + commonData.DfsEndpointSuffix,
                IsDefault     = isDefault,
                FileSystem    = commonData.ContainerName.ToLowerInvariant(),
                ResourceId    = storageResourceId,
                MsiResourceId = msiResourceId
            }
                );

            var identity = new ClusterIdentity
            {
                Type = ResourceIdentityType.UserAssigned,
                UserAssignedIdentities = new Dictionary <string, ClusterIdentityUserAssignedIdentitiesValue>
                {
                    { msiResourceId, new ClusterIdentityUserAssignedIdentitiesValue() }
                }
            };

            if (createParamsForADLSv2.Identity == null)
            {
                createParamsForADLSv2.Identity = identity;
            }
            else
            {
                // At this point, only user-assigned managed identity is supported by HDInsight.
                // So identity type is not checked.
                createParamsForADLSv2.Identity.UserAssignedIdentities.Union(identity.UserAssignedIdentities);
            }

            return(createParamsForADLSv2);
        }
예제 #22
0
        public async Task CanWaitForActivation()
        {
            var activator = GetFakeActivator();
            var timeout   = CancellationTokens.WithTimeout(15 * 1000);
            var identity  = new ClusterIdentity {
                Kind = "thing", Identity = NextId().ToString()
            };
            var spawnLock = await _storage.TryAcquireLock(identity, timeout);

            var pid = Activate(activator, identity);

            _ = SafeTask.Run(async() => {
                await Task.Delay(500, timeout);
                await _storage.StoreActivation(activator.Id, spawnLock !, pid, timeout);
            }, timeout
                             );
            var activation = await _storage.WaitForActivation(identity, timeout);

            activation.Should().NotBeNull();
            activation !.MemberId.Should().Be(activator.Id);
            activation !.Pid.Should().BeEquivalentTo(pid);
        }
예제 #23
0
        public async Task GlobalLockActivatesOnceOnlyAcrossMultipleClients()
        {
            var timeout  = new CancellationTokenSource(1000).Token;
            var identity = new ClusterIdentity {
                Kind = "thing", Identity = "1234"
            };
            const int attempts = 10;

            var locks = await Task.WhenAll(Enumerable.Range(1, attempts)
                                           .SelectMany(_ => new[]
            {
                _storage.TryAcquireLock(identity, timeout),
                _storageInstance2.TryAcquireLock(identity, timeout)
            }
                                                       )
                                           );

            var successfulLock = locks.Where(it => it != null).ToList();

            successfulLock.Should().HaveCount(1);
            successfulLock.Single() !.ClusterIdentity.Should().BeEquivalentTo(identity);
        }
예제 #24
0
        public async Task CannotTakeLockWhenAlreadyActivated()
        {
            var activator = GetFakeActivator();
            var timeout   = new CancellationTokenSource(1000).Token;
            var identity  = new ClusterIdentity {
                Kind = "thing", Identity = NextId().ToString()
            };
            var spawnLock = await _storage.TryAcquireLock(identity, timeout);

            var pid = Activate(activator, identity);
            await _storage.StoreActivation(activator.Id, spawnLock !, pid, timeout);

            var activation = await _storage.TryGetExistingActivation(identity, timeout);

            activation.Should().NotBeNull();
            activation !.MemberId.Should().Be(activator.Id);
            activation !.Pid.Should().BeEquivalentTo(pid);

            var noLock = await _storage.TryAcquireLock(identity, timeout);

            noLock.Should().BeNull("Since the activation is active, it should not be possible to take the lock");
        }
예제 #25
0
        public async Task<StoredActivation?> WaitForActivation(
            ClusterIdentity clusterIdentity,
            CancellationToken ct
        )
        {
            var timer = Stopwatch.StartNew();
            var key = IdKey(clusterIdentity);
            var db = GetDb();

            var activationStatus = await LookupKey(db, key).ConfigureAwait(false);
            var lockId = activationStatus?.ActiveLockId;

            if (lockId != null)
            {
                //There is an active lock on the pid, spin wait
                var i = 1;

                do await Task.Delay(20 * i++, ct);
                while (!ct.IsCancellationRequested
                    && _maxLockTime > timer.Elapsed
                    && (activationStatus = await LookupKey(db, key).ConfigureAwait(false))?.ActiveLockId == lockId
                );
            }

            //the lookup entity was lost, stale lock maybe?
            if (activationStatus == null) return null;

            //lookup was unlocked, return this pid
            if (activationStatus.Activation != null)
                return activationStatus.Activation;

            //Still locked but not by the same request that originally locked it, so not stale
            if (activationStatus.ActiveLockId != lockId) return null;

            //Stale lock. just delete it and let cluster retry
            await RemoveLock(new SpawnLock(lockId!, clusterIdentity), CancellationToken.None).ConfigureAwait(false);

            return null;
        }
        public void DumpState(ClusterIdentity clusterIdentity)
        {
            Console.WriteLine("Memberlist members:");
            _cluster.MemberList.DumpState();

            Console.WriteLine("Partition manager selector:");
            _partitionManager.Selector.DumpState();

            //Get address to node owning this ID
            var identityOwner = _partitionManager.Selector.GetIdentityOwner(clusterIdentity.Identity);

            Console.WriteLine("Identity owner for ID:");
            Console.WriteLine(identityOwner);

            var remotePid = PartitionManager.RemotePartitionIdentityActor(identityOwner);

            var req = new ActivationRequest
            {
                ClusterIdentity = clusterIdentity
            };

            var resp = _cluster.System.Root.RequestAsync <ActivationResponse>(remotePid, req, CancellationTokens.WithTimeout(5000)).Result;

            Console.WriteLine("Target Pid:");

            if (resp == null)
            {
                Console.WriteLine("Null response");
            }
            else if (resp.Pid == null)
            {
                Console.WriteLine("Null PID");
            }
            else
            {
                Console.WriteLine(resp.Pid);
            }
        }
예제 #27
0
        public void CanCreateNewHDInsightCluster_Disk_Encryption()
        {
            string AssignedIdentity     = "/subscriptions/00000000-aaaa-bbbb-cccc-dddddddddddd/resourcegroups/group-unittest/providers/microsoft.managedidentity/userassignedidentities/ami-unittest";
            string EncryptionVaultUri   = "https://vault-unittest.vault.azure.net:443";
            string EncryptionKeyVersion = "00000000000000000000000000000000";
            string EncryptionKeyName    = "key-unittest";
            string EncryptionAlgorithm  = "RSA-OAEP";
            string sparkClusterType     = "Spark";

            cmdlet.ClusterName               = ClusterName;
            cmdlet.ResourceGroupName         = ResourceGroupName;
            cmdlet.ClusterSizeInNodes        = ClusterSize;
            cmdlet.Location                  = Location;
            cmdlet.HttpCredential            = _httpCred;
            cmdlet.DefaultStorageAccountName = StorageName;
            cmdlet.DefaultStorageAccountKey  = StorageKey;
            cmdlet.ClusterType               = "Spark";
            cmdlet.SshCredential             = _sshCred;
            cmdlet.EncryptionAlgorithm       = EncryptionAlgorithm;
            cmdlet.EncryptionKeyName         = EncryptionKeyName;
            cmdlet.EncryptionKeyVersion      = EncryptionKeyVersion;
            cmdlet.EncryptionVaultUri        = EncryptionVaultUri;
            cmdlet.AssignedIdentity          = AssignedIdentity;

            var ClusterIdentity = new ClusterIdentity
            {
                Type = ResourceIdentityType.UserAssigned,
                UserAssignedIdentities = new Dictionary <string, ClusterIdentityUserAssignedIdentitiesValue>
                {
                    {
                        AssignedIdentity, new ClusterIdentityUserAssignedIdentitiesValue(principalId: "PrincipalId", clientId: "ClientId")
                    }
                }
            };

            var cluster = new Cluster(id: "id", name: ClusterName, identity: ClusterIdentity)
            {
                Location   = Location,
                Properties = new ClusterGetProperties
                {
                    ClusterVersion    = "3.6",
                    ClusterState      = "Running",
                    ClusterDefinition = new ClusterDefinition
                    {
                        Kind = sparkClusterType
                    },
                    QuotaInfo = new QuotaInfo
                    {
                        CoresUsed = 24
                    },
                    OsType = OSType.Linux,
                    DiskEncryptionProperties = new DiskEncryptionProperties()
                    {
                        KeyName             = EncryptionKeyName,
                        KeyVersion          = EncryptionKeyVersion,
                        VaultUri            = EncryptionVaultUri,
                        EncryptionAlgorithm = EncryptionAlgorithm,
                        MsiResourceId       = AssignedIdentity
                    },
                },
            };

            var coreConfigs = new Dictionary <string, string>
            {
                { "fs.defaultFS", "wasb://giyertestcsmv2@" + StorageName },
                {
                    "fs.azure.account.key." + StorageName,
                    StorageKey
                }
            };
            var gatewayConfigs = new Dictionary <string, string>
            {
                { "restAuthCredential.isEnabled", "true" },
                { "restAuthCredential.username", _httpCred.UserName },
                { "restAuthCredential.password", _httpCred.Password.ConvertToString() }
            };

            var configurations = new Dictionary <string, Dictionary <string, string> >
            {
                { "core-site", coreConfigs },
                { "gateway", gatewayConfigs }
            };
            var serializedConfig = JsonConvert.SerializeObject(configurations);

            cluster.Properties.ClusterDefinition.Configurations = serializedConfig;

            hdinsightManagementMock.Setup(c => c.CreateNewCluster(ResourceGroupName, ClusterName, OSType.Linux, It.Is <ClusterCreateParameters>(
                                                                      parameters =>
                                                                      parameters.ClusterSizeInNodes == ClusterSize &&
                                                                      parameters.DefaultStorageInfo as AzureStorageInfo != null &&
                                                                      ((AzureStorageInfo)parameters.DefaultStorageInfo).StorageAccountName == StorageName &&
                                                                      ((AzureStorageInfo)parameters.DefaultStorageInfo).StorageAccountKey == StorageKey &&
                                                                      parameters.Location == Location &&
                                                                      parameters.UserName == _httpCred.UserName &&
                                                                      parameters.Password == _httpCred.Password.ConvertToString() &&
                                                                      parameters.ClusterType == sparkClusterType &&
                                                                      parameters.SshUserName == _sshCred.UserName &&
                                                                      parameters.SshPassword == _sshCred.Password.ConvertToString() &&
                                                                      parameters.DiskEncryptionProperties.VaultUri == EncryptionVaultUri &&
                                                                      parameters.DiskEncryptionProperties.KeyName == EncryptionKeyName &&
                                                                      parameters.DiskEncryptionProperties.KeyVersion == EncryptionKeyVersion &&
                                                                      parameters.DiskEncryptionProperties.EncryptionAlgorithm == EncryptionAlgorithm &&
                                                                      parameters.DiskEncryptionProperties.MsiResourceId == AssignedIdentity), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <bool?>()))
            .Returns(cluster)
            .Verifiable();

            cmdlet.ExecuteCmdlet();

            commandRuntimeMock.VerifyAll();
            commandRuntimeMock.Verify(f => f.WriteObject(It.Is <AzureHDInsightCluster>(
                                                             clusterout =>
                                                             clusterout.ClusterState == "Running" &&
                                                             clusterout.ClusterType == sparkClusterType &&
                                                             clusterout.ClusterVersion == "3.6" &&
                                                             clusterout.CoresUsed == 24 &&
                                                             clusterout.Location == Location &&
                                                             clusterout.Name == ClusterName &&
                                                             clusterout.OperatingSystemType == OSType.Linux &&
                                                             clusterout.DiskEncryption.KeyName == EncryptionKeyName &&
                                                             clusterout.DiskEncryption.KeyVersion == EncryptionKeyVersion &&
                                                             clusterout.DiskEncryption.VaultUri == EncryptionVaultUri &&
                                                             clusterout.DiskEncryption.EncryptionAlgorithm == EncryptionAlgorithm &&
                                                             clusterout.DiskEncryption.MsiResourceId == AssignedIdentity &&
                                                             clusterout.AssignedIdentity.Type == ResourceIdentityType.UserAssigned &&
                                                             clusterout.AssignedIdentity.UserAssignedIdentities[AssignedIdentity].ClientId == "ClientId" &&
                                                             clusterout.AssignedIdentity.UserAssignedIdentities[AssignedIdentity].PrincipalId == "PrincipalId"
                                                             )), Times.Once);
        }
        public override void ExecuteCmdlet()
        {
            foreach (var component in ComponentVersion.Where(component => !clusterComponentVersion.ContainsKey(component.Key)))
            {
                clusterComponentVersion.Add(component.Key, component.Value);
            }
            // Construct Configurations
            foreach (var config in Configurations.Where(config => !clusterConfigurations.ContainsKey(config.Key)))
            {
                clusterConfigurations.Add(config.Key, config.Value);
            }

            // Add cluster username/password to gateway config.
            ClusterCreateHelper.AddClusterCredentialToGatewayConfig(HttpCredential, clusterConfigurations);

            // Construct OS Profile
            OsProfile osProfile = ClusterCreateHelper.CreateOsProfile(SshCredential, SshPublicKey);

            // Construct Virtual Network Profile
            VirtualNetworkProfile vnetProfile = ClusterCreateHelper.CreateVirtualNetworkProfile(VirtualNetworkId, SubnetName);

            // Handle storage account
            StorageProfile storageProfile = new StorageProfile()
            {
                Storageaccounts = new List <StorageAccount> {
                }
            };

            if (StorageAccountType == null || StorageAccountType == StorageType.AzureStorage)
            {
                var azureStorageAccount = ClusterCreateHelper.CreateAzureStorageAccount(ClusterName, StorageAccountResourceId, StorageAccountKey, StorageContainer, this.DefaultContext.Environment.StorageEndpointSuffix);
                storageProfile.Storageaccounts.Add(azureStorageAccount);
            }
            else if (StorageAccountType == StorageType.AzureDataLakeStore)
            {
                ClusterCreateHelper.AddAzureDataLakeStorageGen1ToCoreConfig(StorageAccountResourceId, StorageRootPath, this.DefaultContext.Environment.AzureDataLakeStoreFileSystemEndpointSuffix, clusterConfigurations);
            }
            else if (StorageAccountType == StorageType.AzureDataLakeStorageGen2)
            {
                var adlsgen2Account = ClusterCreateHelper.CreateAdlsGen2StorageAccount(ClusterName, StorageAccountResourceId, StorageAccountKey, StorageFileSystem, StorageAccountManagedIdentity, this.DefaultContext.Environment.StorageEndpointSuffix);
                storageProfile.Storageaccounts.Add(adlsgen2Account);
            }

            // Handle additional storage accounts
            foreach (
                var storageAccount in
                AdditionalStorageAccounts.Where(
                    storageAccount => !clusterAdditionalStorageAccounts.ContainsKey(storageAccount.Key)))
            {
                clusterAdditionalStorageAccounts.Add(storageAccount.Key, storageAccount.Value);
            }
            ClusterCreateHelper.AddAdditionalStorageAccountsToCoreConfig(clusterAdditionalStorageAccounts, clusterConfigurations);

            // Handle script action
            foreach (var action in ScriptActions.Where(action => clusterScriptActions.ContainsKey(action.Key)))
            {
                clusterScriptActions.Add(action.Key,
                                         action.Value.Select(a => a.GetScriptActionFromPSModel()).ToList());
            }

            // Handle metastore
            if (OozieMetastore != null)
            {
                ClusterCreateHelper.AddOozieMetastoreToConfigurations(OozieMetastore, clusterConfigurations);
            }
            if (HiveMetastore != null)
            {
                ClusterCreateHelper.AddHiveMetastoreToConfigurations(HiveMetastore, clusterConfigurations);
            }

            // Handle ADLSGen1 identity
            if (!string.IsNullOrEmpty(CertificatePassword))
            {
                if (!string.IsNullOrEmpty(CertificateFilePath))
                {
                    CertificateFileContents = File.ReadAllBytes(CertificateFilePath);
                }

                ClusterCreateHelper.AddDataLakeStorageGen1IdentityToIdentityConfig(
                    GetApplicationId(ApplicationId), GetTenantId(AadTenantId), CertificateFileContents, CertificatePassword, clusterConfigurations,
                    this.DefaultContext.Environment.ActiveDirectoryAuthority, this.DefaultContext.Environment.DataLakeEndpointResourceId);
            }

            // Handle Kafka Rest Proxy
            KafkaRestProperties kafkaRestProperties = null;

            if (KafkaClientGroupId != null && KafkaClientGroupName != null)
            {
                kafkaRestProperties = new KafkaRestProperties()
                {
                    ClientGroupInfo = new ClientGroupInfo(KafkaClientGroupName, KafkaClientGroupId)
                };
            }

            // Compute profile contains headnode, workernode, zookeepernode, edgenode, kafkamanagementnode, idbrokernode, etc.
            ComputeProfile computeProfile = ClusterCreateHelper.CreateComputeProfile(osProfile, vnetProfile, clusterScriptActions, ClusterType, ClusterSizeInNodes, HeadNodeSize, WorkerNodeSize, ZookeeperNodeSize, EdgeNodeSize, KafkaManagementNodeSize, EnableIDBroker.IsPresent);

            // Handle SecurityProfile
            SecurityProfile securityProfile = ClusterCreateHelper.ConvertAzureHDInsightSecurityProfileToSecurityProfile(SecurityProfile, AssignedIdentity);

            // Handle DisksPerWorkerNode feature
            Role workerNode = Utils.ExtractRole(ClusterNodeType.WorkerNode.ToString(), computeProfile);

            if (DisksPerWorkerNode > 0)
            {
                workerNode.DataDisksGroups = new List <DataDisksGroups>()
                {
                    new DataDisksGroups()
                    {
                        DisksPerNode = DisksPerWorkerNode
                    }
                };
            }

            // Handle ClusterIdentity
            ClusterIdentity clusterIdentity = null;

            if (AssignedIdentity != null || StorageAccountManagedIdentity != null)
            {
                clusterIdentity = new ClusterIdentity
                {
                    Type = ResourceIdentityType.UserAssigned,
                    UserAssignedIdentities = new Dictionary <string, ClusterIdentityUserAssignedIdentitiesValue>()
                };
                if (AssignedIdentity != null)
                {
                    clusterIdentity.UserAssignedIdentities.Add(AssignedIdentity, new ClusterIdentityUserAssignedIdentitiesValue());
                }
                if (StorageAccountManagedIdentity != null)
                {
                    clusterIdentity.UserAssignedIdentities.Add(StorageAccountManagedIdentity, new ClusterIdentityUserAssignedIdentitiesValue());
                }
            }

            // Handle CMK feature
            DiskEncryptionProperties diskEncryptionProperties = null;

            if (EncryptionKeyName != null && EncryptionKeyVersion != null && EncryptionVaultUri != null)
            {
                diskEncryptionProperties = new DiskEncryptionProperties()
                {
                    KeyName             = EncryptionKeyName,
                    KeyVersion          = EncryptionKeyVersion,
                    VaultUri            = EncryptionVaultUri,
                    EncryptionAlgorithm = EncryptionAlgorithm != null ? EncryptionAlgorithm : JsonWebKeyEncryptionAlgorithm.RSAOAEP,
                    MsiResourceId       = AssignedIdentity
                };
            }

            // Handle encryption at host feature
            if (EncryptionAtHost != null)
            {
                if (diskEncryptionProperties != null)
                {
                    diskEncryptionProperties.EncryptionAtHost = EncryptionAtHost;
                }
                else
                {
                    diskEncryptionProperties = new DiskEncryptionProperties()
                    {
                        EncryptionAtHost = EncryptionAtHost
                    };
                }
            }

            // Handle autoscale featurer
            Autoscale autoscaleParameter = null;

            if (AutoscaleConfiguration != null)
            {
                autoscaleParameter = AutoscaleConfiguration.ToAutoscale();
                workerNode.AutoscaleConfiguration = autoscaleParameter;
            }

            // Construct cluster create parameter
            ClusterCreateParametersExtended createParams = new ClusterCreateParametersExtended
            {
                Location = Location,
                //Tags = Tags,  //To Do add this Tags parameter
                Properties = new ClusterCreateProperties
                {
                    Tier = ClusterTier,
                    ClusterDefinition = new ClusterDefinition
                    {
                        Kind             = ClusterType ?? "Hadoop",
                        ComponentVersion = clusterComponentVersion,
                        Configurations   = clusterConfigurations
                    },
                    ClusterVersion      = Version ?? "default",
                    KafkaRestProperties = kafkaRestProperties,
                    ComputeProfile      = computeProfile,
                    OsType                   = OSType,
                    SecurityProfile          = securityProfile,
                    StorageProfile           = storageProfile,
                    DiskEncryptionProperties = diskEncryptionProperties,
                    //handle Encryption In Transit feature
                    EncryptionInTransitProperties = EncryptionInTransit != null ? new EncryptionInTransitProperties()
                    {
                        IsEncryptionInTransitEnabled = EncryptionInTransit
                    } : null,
                    MinSupportedTlsVersion = MinSupportedTlsVersion
                },
                Identity = clusterIdentity
            };

            var cluster = HDInsightManagementClient.CreateCluster(ResourceGroupName, ClusterName, createParams);

            if (cluster != null)
            {
                WriteObject(new AzureHDInsightCluster(cluster));
            }
        }
 private string GetKey(ClusterIdentity clusterIdentity) => $"{_clusterName}/{clusterIdentity}";
예제 #30
0
 private RedisKey IdKey(ClusterIdentity clusterIdentity) => _clusterIdentityKey.Append(clusterIdentity.ToString());