1- using System . Collections . Generic ;
1+ using System ;
2+ using System . Collections . Generic ;
23using System . Linq ;
34using System . Reflection ;
5+ using HEAppE . BusinessLogicTier . Configuration ;
6+ using HEAppE . BusinessLogicTier . Factory ;
47using HEAppE . DataAccessTier . UnitOfWork ;
58using HEAppE . DomainObjects . ClusterInformation ;
69using HEAppE . DomainObjects . JobManagement ;
@@ -51,27 +54,51 @@ public IEnumerable<Cluster> ListAvailableClusters()
5154
5255 public ClusterNodeUsage GetCurrentClusterNodeUsage ( long clusterNodeId , AdaptorUser loggedUser , long projectId )
5356 {
54- var nodeType = GetClusterNodeTypeById ( clusterNodeId ) ;
55- var project = _unitOfWork . ProjectRepository . GetById ( projectId ) ;
56- if ( ! nodeType . ClusterId . HasValue ) throw new InvalidRequestException ( "ClusterNodeNoReferenceToCluster" ) ;
57+ var nodeType = GetClusterNodeTypeById ( clusterNodeId )
58+ ?? throw new RequestedObjectDoesNotExistException ( "ClusterNodeTypeNotFound" , clusterNodeId ) ;
59+
60+ var project = _unitOfWork . ProjectRepository . GetById ( projectId )
61+ ?? throw new RequestedObjectDoesNotExistException ( "ProjectNotFound" , projectId ) ;
62+
63+ var cluster = nodeType . Cluster
64+ ?? throw new InvalidRequestException ( "ClusterNodeNoReferenceToCluster" , clusterNodeId ) ;
65+
66+ if ( ! nodeType . ClusterId . HasValue )
67+ throw new InvalidRequestException ( "ClusterNodeNoReferenceToClusterId" , clusterNodeId ) ;
5768
58- if ( project is null ) throw new RequestedObjectDoesNotExistException ( "ProjectNotFound" ) ;
69+ if ( loggedUser ? . Groups == null || ! loggedUser . Groups . Any ( ) )
70+ throw new InvalidRequestException ( "UserHasNoGroups" , loggedUser ) ;
71+
72+ var clusterProjectIds = cluster . ClusterProjects ?
73+ . Where ( x => x . ProjectId == projectId )
74+ . Select ( y => y . ProjectId )
75+ . ToList ( ) ?? new List < long > ( ) ;
76+
77+ var availableProjectIds = loggedUser . Groups
78+ . Where ( g => g . ProjectId . HasValue && clusterProjectIds . Contains ( g . ProjectId . Value ) )
79+ . Select ( g => g . ProjectId ! . Value )
80+ . Distinct ( )
81+ . ToList ( ) ;
5982
60- var clusterProjectIds = nodeType . Cluster . ClusterProjects . Where ( x => x . ProjectId == projectId )
61- . Select ( y => y . ProjectId ) ;
62- var availableProjectIds = loggedUser . Groups . Where ( g => clusterProjectIds . Contains ( g . ProjectId . Value ) )
63- . Select ( x => x . ProjectId . Value ) . Distinct ( ) . ToList ( ) ;
6483 if ( availableProjectIds . Count == 0 )
6584 throw new InvalidRequestException ( "UserNoAccessToClusterNode" , loggedUser , clusterNodeId ) ;
66- var serviceAccount =
67- _unitOfWork . ClusterAuthenticationCredentialsRepository . GetServiceAccountCredentials (
68- nodeType . ClusterId . Value , projectId ) ;
69- return serviceAccount is null
70- ? throw new InvalidRequestException ( "ProjectNoReferenceToCluster" , projectId , nodeType . ClusterId . Value )
71- : SchedulerFactory . GetInstance ( nodeType . Cluster . SchedulerType ) . CreateScheduler ( nodeType . Cluster , project )
72- . GetCurrentClusterNodeUsage ( nodeType , serviceAccount ) ;
85+
86+ var serviceAccount = _unitOfWork . ClusterAuthenticationCredentialsRepository
87+ ? . GetServiceAccountCredentials ( cluster . Id , projectId , requireIsInitialized : true , adaptorUserId : loggedUser . Id ) ;
88+
89+ if ( serviceAccount is null )
90+ throw new InvalidRequestException ( "ProjectNoReferenceToCluster" , projectId , cluster . Id ) ;
91+
92+ var schedulerFactory = SchedulerFactory . GetInstance ( cluster . SchedulerType )
93+ ?? throw new InvalidOperationException ( "SchedulerFactoryInstanceIsNull" ) ;
94+
95+ var scheduler = schedulerFactory . CreateScheduler ( cluster , project , adaptorUserId : loggedUser . Id )
96+ ?? throw new InvalidOperationException ( "SchedulerInitializationFailed" ) ;
97+
98+ return scheduler . GetCurrentClusterNodeUsage ( nodeType , serviceAccount ) ;
7399 }
74100
101+
75102 public IEnumerable < string > GetCommandTemplateParametersName ( long commandTemplateId , long projectId ,
76103 string userScriptPath , AdaptorUser loggedUser )
77104 {
@@ -97,37 +124,92 @@ public IEnumerable<string> GetCommandTemplateParametersName(long commandTemplate
97124 var cluster = commandTemplate . ClusterNodeType . Cluster ;
98125 var serviceAccountCredentials =
99126 _unitOfWork . ClusterAuthenticationCredentialsRepository . GetServiceAccountCredentials ( cluster . Id ,
100- projectId ) ;
127+ projectId , requireIsInitialized : true , adaptorUserId : loggedUser . Id ) ;
101128 if ( serviceAccountCredentials is null )
102129 throw new RequestedObjectDoesNotExistException ( "ServiceAccountCredentialsNotDefinedInCommandTemplate" ) ;
103130
104131 var commandTemplateParameters = new List < string > { scriptPath } ;
105132 commandTemplateParameters . AddRange ( SchedulerFactory . GetInstance ( cluster . SchedulerType )
106- . CreateScheduler ( cluster , project )
133+ . CreateScheduler ( cluster , project , adaptorUserId : loggedUser . Id )
107134 . GetParametersFromGenericUserScript ( cluster , serviceAccountCredentials , userScriptPath ) . ToList ( ) ) ;
108135 return commandTemplateParameters ;
109136 }
110137
111138 return commandTemplate . TemplateParameters . Select ( s => s . Identifier )
112139 . ToList ( ) ;
113140 }
141+
142+ private IEnumerable < ClusterAuthenticationCredentials > InitializeCredentials ( long projectId , long clusterId , long ? adaptorUserId )
143+ {
144+ var credentials =
145+ _unitOfWork . ClusterAuthenticationCredentialsRepository . GetAuthenticationCredentialsForClusterAndProject (
146+ clusterId , projectId , false , null ) ;
147+ var managementLogic = LogicFactory . GetLogicFactory ( ) . CreateManagementLogic ( _unitOfWork ) ;
148+ foreach ( var credential in credentials )
149+ {
150+ var status = managementLogic . InitializeClusterScriptDirectory (
151+ projectId ,
152+ true ,
153+ adaptorUserId : adaptorUserId . HasValue ? adaptorUserId . Value : null ,
154+ username : credential . Username
155+ ) ;
156+ _log . Info ( $ "Initialized credential { credential . Username } for project { projectId } with status: { status } ") ;
157+ }
158+ return credentials ;
159+ }
114160
115- public ClusterAuthenticationCredentials GetNextAvailableUserCredentials ( long clusterId , long projectId )
161+ public ClusterAuthenticationCredentials GetNextAvailableUserCredentials ( long clusterId , long projectId , bool requireIsInitialized , long ? adaptorUserId )
116162 {
117163 var cluster = _unitOfWork . ClusterRepository . GetById ( clusterId ) ;
164+ if ( cluster == null )
165+ throw new RequestedObjectDoesNotExistException ( "ClusterNotExists" , clusterId ) ;
118166
119- if ( cluster == null ) throw new RequestedObjectDoesNotExistException ( "ClusterNotExists" , clusterId ) ;
167+ var project = _unitOfWork . ProjectRepository . GetById ( projectId ) ;
168+ if ( project == null )
169+ throw new RequestedObjectDoesNotExistException ( "ProjectNotExists" , projectId ) ;
120170
171+ if ( project . IsOneToOneMapping )
172+ {
173+ try
174+ {
175+ return GetNextAvailableUserCredentialsByAdaptorUser ( clusterId , projectId , requireIsInitialized ,
176+ adaptorUserId . Value ) ;
177+ }
178+ catch ( NotAllowedException ex )
179+ {
180+ if ( BusinessLogicConfiguration . AutomaticClusterAccountInitialization )
181+ {
182+ _log . Info ( $ "Automatic initialization of cluster accounts is enabled. Attempting to initialize accounts for project { projectId } on cluster { clusterId } for adaptor user { adaptorUserId } ") ;
183+ var initializedCredentials = InitializeCredentials ( projectId , clusterId , adaptorUserId ) ;
184+ return GetNextAvailableUserCredentialsByAdaptorUser ( clusterId , projectId , requireIsInitialized ,
185+ adaptorUserId . Value ) ;
186+ }
187+ }
188+ }
189+
121190 //return all non service account for specific cluster and project
122- var credentials =
123- _unitOfWork . ClusterAuthenticationCredentialsRepository . GetAuthenticationCredentialsForClusterAndProject (
124- clusterId , projectId ) ;
191+ IEnumerable < ClusterAuthenticationCredentials > credentials = new List < ClusterAuthenticationCredentials > ( ) ;
192+ try
193+ {
194+ credentials =
195+ _unitOfWork . ClusterAuthenticationCredentialsRepository . GetAuthenticationCredentialsForClusterAndProject (
196+ clusterId , projectId , requireIsInitialized , null ) ;
197+ }
198+ catch ( NotAllowedException ex )
199+ {
200+ if ( BusinessLogicConfiguration . AutomaticClusterAccountInitialization )
201+ {
202+ _log . Info ( $ "Automatic initialization of cluster accounts is enabled. Attempting to initialize accounts for project { projectId } on cluster { clusterId } ") ;
203+ credentials = InitializeCredentials ( projectId , clusterId , null ) ;
204+ }
205+ }
206+
125207 if ( credentials == null || credentials ? . Count ( ) == 0 )
126208 throw new RequestedObjectDoesNotExistException ( "ClusterProjectCombinationNotFound" , clusterId , projectId ) ;
209+
127210 var serviceCredentials =
128- _unitOfWork . ClusterAuthenticationCredentialsRepository . GetServiceAccountCredentials ( clusterId , projectId )
129- ?? throw new RequestedObjectDoesNotExistException ( "ClusterProjectCombinationNoServiceAccount" , clusterId ,
130- projectId ) ;
211+ _unitOfWork . ClusterAuthenticationCredentialsRepository . GetServiceAccountCredentials ( clusterId , projectId , requireIsInitialized , null )
212+ ?? throw new RequestedObjectDoesNotExistException ( "ClusterProjectCombinationNoServiceAccount" , clusterId , projectId ) ;
131213
132214 var firstCredentials = credentials . FirstOrDefault ( ) ;
133215
@@ -152,6 +234,41 @@ public ClusterAuthenticationCredentials GetNextAvailableUserCredentials(long clu
152234 return creds ;
153235 }
154236
237+ private ClusterAuthenticationCredentials GetNextAvailableUserCredentialsByAdaptorUser ( long clusterId , long projectId , bool requireIsInitialized , long adaptorUserId )
238+ {
239+ //return all non service account for specific cluster and project
240+ var credentials =
241+ _unitOfWork . ClusterAuthenticationCredentialsRepository . GetAuthenticationCredentialsForClusterAndProject (
242+ clusterId , projectId , requireIsInitialized , adaptorUserId ) ;
243+ if ( credentials == null || credentials ? . Count ( ) == 0 )
244+ throw new RequestedObjectDoesNotExistException ( "ClusterProjectCombinationNotFound" , clusterId , projectId ) ;
245+
246+ var serviceCredentials =
247+ _unitOfWork . ClusterAuthenticationCredentialsRepository . GetServiceAccountCredentials ( clusterId , projectId , requireIsInitialized , adaptorUserId )
248+ ?? throw new RequestedObjectDoesNotExistException ( "ClusterAuthenticationCredentialsNoServiceAccount" , clusterId , projectId , adaptorUserId ) ;
249+
250+ var firstCredentials = credentials . FirstOrDefault ( ) ;
251+ var lastUsedId = AdaptorUserProjectClusterUserCache . GetLastUserId ( adaptorUserId , projectId , clusterId ) ;
252+ if ( lastUsedId is null )
253+ {
254+ // No user has been used from this cluster
255+ // return first usable account
256+ AdaptorUserProjectClusterUserCache . SetLastUserId ( adaptorUserId , projectId , clusterId , serviceCredentials . Id , firstCredentials . Id ) ;
257+ _log . DebugFormat ( "Using initial cluster account: {0}" , firstCredentials . Username ) ;
258+ return firstCredentials ;
259+ }
260+
261+ // Return first user with Id higher than the last one
262+ var creds = ( from account in credentials where account . Id > lastUsedId select account ) . FirstOrDefault ( ) ;
263+ // No credentials with Id higher than last used found
264+ // use first usable account
265+ creds ??= firstCredentials ;
266+
267+ AdaptorUserProjectClusterUserCache . SetLastUserId ( adaptorUserId , projectId , clusterId , serviceCredentials . Id , creds . Id ) ;
268+ _log . DebugFormat ( "Using cluster account: {0}" , creds . Username ) ;
269+ return creds ;
270+ }
271+
155272 public ClusterNodeType GetClusterNodeTypeById ( long clusterNodeTypeId )
156273 {
157274 var nodeType = _unitOfWork . ClusterNodeTypeRepository . GetById ( clusterNodeTypeId ) ;
0 commit comments