Skip to content
Snippets Groups Projects
Program.cs 14.8 KiB
Newer Older
  • Learn to ignore specific revisions
  • Vaclav Svaton's avatar
    Vaclav Svaton committed
    using Renci.SshNet;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Security.Cryptography;
    using System.Text;
    using System.Threading.Tasks;
    
    using WsClient.localhost_ClusterInformationWs;
    using WsClient.localhost_DataTransferWs;
    using WsClient.localhost_FileTransferWs;
    using WsClient.localhost_JobManagementWs;
    using WsClient.localhost_JobReportingWs;
    using WsClient.localhost_UserAndLimitationManagementWs;
    
    using JobPriorityExt = WsClient.localhost_JobManagementWs.JobPriorityExt;
    using JobStateExt = WsClient.localhost_JobManagementWs.JobStateExt;
    
    namespace WsClient
    {
        class Program
        {
            static ClusterInformationWs wsClusterInformation = new ClusterInformationWs();
            static DataTransferWs wsDataTransfer = new DataTransferWs();
            static FileTransferWs wsFileTransfer = new FileTransferWs();
            static JobManagementWs wsJobManagement = new JobManagementWs();
            static JobReportingWs wsJobReporting = new JobReportingWs();
            static UserAndLimitationManagementWs wsUserAndLimitationManagement = new UserAndLimitationManagementWs();
    
            private static string sessionCode;
            private const string TEST_USER = "test";
            private const string TEST_USER_PRIVATE_KEY = "<RSAKeyValue>somersakey</RSAKeyValue>";
    
    
            static void Main(string[] args)
            {
                //AuthenticateUserCredentials();
                AuthenticateUserPassword();
    
                //ListAdaptorUserGroups();
                //GetUserResourceUsageReport();
                //GetUserGroupResourceUsageReport();
    
                //ListAvailableClusters();
                //ListJobTemplates();
                
                CreateAndSubmitTestJob();
            }
    
            private static void ListAdaptorUserGroups()
            {
                Console.WriteLine("ListAdaptorUserGroups ...");
                AdaptorUserGroupExt[] groups = wsJobReporting.ListAdaptorUserGroups(sessionCode);
                foreach (AdaptorUserGroupExt group in groups)
                {
                    foreach (AdaptorUserExt user in group.users)
                        Console.WriteLine("groupId = {0}, groupName = {1}, userId = {2}, userName = {3}", group.id, group.name, user.id, user.username);
                }
            }
    
            private static void GetUserResourceUsageReport()
            {
                long userId = 1;
                UserResourceUsageReportExt report = wsJobReporting.GetUserResourceUsageReport(userId, new DateTime(2017, 1, 1), DateTime.Now, sessionCode);
                Console.WriteLine("userId = {0}, nodeTypeReports = {1}, totalCorehoursUsage = {2} ... details included", report.user.id, report.nodeTypeReports.Count(), report.totalCorehoursUsage);
            }
    
            private static void GetUserGroupResourceUsageReport()
            {
                long groupId = 1;
                UserGroupResourceUsageReportExt report = wsJobReporting.GetUserGroupResourceUsageReport(groupId, new DateTime(2017, 1, 1), DateTime.Now, sessionCode);
                foreach (UserAggregatedUsageExt userReport in report.userReports)
                {
                    Console.WriteLine("groupId = {0}, userId = {1}, nodeTypeReports = {2}, totalCorehoursUsage = {3} ... details included", groupId, userReport.user.id, 
                        userReport.nodeTypeReports.Count(), userReport.totalCorehoursUsage);
                }
            }
    
            private static void CreateAndSubmitTestJob()
            {
                TaskSpecificationExt testTask = new TaskSpecificationExt();
                testTask.name = "TestJob";
                testTask.minCores = 1;
                testTask.maxCores = 1;
                testTask.walltimeLimit = 600;
                //testTask.requiredNodes = null;
                //testTask.isExclusive = false;
                //testTask.isRerunnable = false;
                //testTask.standardInputFile = null;
                testTask.standardOutputFile = "console_Stdout";
                testTask.standardErrorFile = "console_Stderr";
                testTask.progressFile = "console_Stdprog";
                testTask.logFile = "console_Stdlog";
                //testTask.clusterTaskSubdirectory = null;
                testTask.commandTemplateId = 1;                                     //commandTemplateID
                testTask.environmentVariables = new EnvironmentVariableExt[0];
                //testTask.dependsOn = null;
                testTask.templateParameterValues = new CommandTemplateParameterValueExt[] { 
                    new CommandTemplateParameterValueExt() { commandParameterIdentifier = "inputParam", parameterValue = "someStringParam" } 
                };
    
                JobSpecificationExt testJob = new JobSpecificationExt();
                testJob.name = "TestJob";
                testJob.minCores = 1;
                testJob.maxCores = 1;
                testJob.priority = JobPriorityExt.Average;
                testJob.project = "ExpTests";
                testJob.waitingLimit = null;
                testJob.walltimeLimit = 600;
                //testJob.notificationEmail = "some.name@mail.cz";
                //testJob.phoneNumber = "999111000";
                //testJob.notifyOnAbort = false;
                //testJob.notifyOnFinish = false;
                //testJob.notifyOnStart = false;
                testJob.clusterNodeTypeId = 7;
                testJob.environmentVariables = new EnvironmentVariableExt[0];
                testJob.tasks = new TaskSpecificationExt[] { testTask };
    
                //create job
                SubmittedJobInfoExt submittedTestJob = wsJobManagement.CreateJob(testJob, sessionCode);
                Console.WriteLine("Created job ID {0}.", submittedTestJob.id);
    
                //upload input files
                FileTransferMethodExt ft = wsFileTransfer.GetFileTransferMethod((long)submittedTestJob.id, sessionCode);
                using (MemoryStream pKeyStream = new MemoryStream(Encoding.UTF8.GetBytes(ft.credentials.privateKey)))
                {
                    using (ScpClient scpClient = new ScpClient(ft.serverHostname, ft.credentials.username, new PrivateKeyFile(pKeyStream)))
                    {
                        scpClient.Connect();
                        DirectoryInfo di = new DirectoryInfo(@"C:\InputFiles\");
                        foreach (FileInfo fi in di.GetFiles())
                        {
                            Console.WriteLine("Uploading file: " + fi.Name);
                            scpClient.Upload(fi, ft.sharedBasepath + "//" + fi.Name);
                            Console.WriteLine("File uploaded.");
                        }
                    }
                }
                wsFileTransfer.EndFileTransfer((long)submittedTestJob.id, ft, sessionCode);
                
                //submit job
                submittedTestJob = wsJobManagement.SubmitJob((long)submittedTestJob.id, sessionCode);
                Console.WriteLine("Submitted job ID: {0}", submittedTestJob.id);
    
                //check status of running job (submitted, configuring, queued, running)
                SubmittedJobInfoExt submittedJob;
                long jobId = (long)submittedTestJob.id;
                int iteration = 0;
                do
                {
                    ++iteration;
                    
                    System.Threading.Thread.Sleep(30000);
    
                    submittedJob = wsJobManagement.GetCurrentInfoForJob(jobId, sessionCode);
                    Console.WriteLine(submittedJob.state);
    
                    //reset offsets to 0
                    List<TaskFileOffsetExt> offsets = new List<TaskFileOffsetExt>();
                    foreach (SubmittedTaskInfoExt taskInfo in submittedJob.tasks)
                    {
                        TaskFileOffsetExt off = new TaskFileOffsetExt();
                        off.fileType = SynchronizableFilesExt.LogFile;
                        off.submittedTaskInfoId = taskInfo.id;
                        off.offset = 0;
                        offsets.Add(off);
    
                        off = new TaskFileOffsetExt();
                        off.fileType = SynchronizableFilesExt.ProgressFile;
                        off.submittedTaskInfoId = taskInfo.id;
                        off.offset = 0;
                        offsets.Add(off);
    
                        off = new TaskFileOffsetExt();
                        off.fileType = SynchronizableFilesExt.StandardErrorFile;
                        off.submittedTaskInfoId = taskInfo.id;
                        off.offset = 0;
                        offsets.Add(off);
    
                        off = new TaskFileOffsetExt();
                        off.fileType = SynchronizableFilesExt.StandardOutputFile;
                        off.submittedTaskInfoId = taskInfo.id;
                        off.offset = 0;
                        offsets.Add(off);
                    }
    
                    //donwload stdouts based on offsets
                    JobFileContentExt[] result = wsFileTransfer.DownloadPartsOfJobFilesFromCluster(jobId, offsets.ToArray(), sessionCode);
                    foreach (JobFileContentExt file in result)
                    {
                        Console.WriteLine("File: " + file.fileType + ", " + file.relativePath);
                        Console.WriteLine("TaskInfoId: " + file.submittedTaskInfoId);
                        Console.WriteLine("Offset: " + file.offset);
                        Console.WriteLine("Content: " + file.content);
                    }
    
                    //cancel job
                    //if (iteration == 5)
                    //{
                    //    Console.WriteLine("Canceling job ...");
                    //    wsJobManagement.CancelJob((long)submittedJob.id, sessionCode);
                    //}
                }
                while (submittedJob.state == JobStateExt.Submitted || submittedJob.state == JobStateExt.Configuring
                    || submittedJob.state == JobStateExt.Queued || submittedJob.state == JobStateExt.Running);
    
                //job computation is done (finished, failed, canceled)
                submittedJob = wsJobManagement.GetCurrentInfoForJob(jobId, sessionCode);
                if (submittedJob.state == JobStateExt.Finished) // job finished successfully
                {
                    ft = wsFileTransfer.GetFileTransferMethod(jobId, sessionCode);
                    using (MemoryStream pKeyStream = new MemoryStream(Encoding.UTF8.GetBytes(ft.credentials.privateKey)))
                    {
                        using (ScpClient scpClient = new ScpClient(ft.serverHostname, ft.credentials.username, new PrivateKeyFile(pKeyStream)))
                        {
                            scpClient.Connect();
    
                            //changed result files
                            string[] changedFiles = wsFileTransfer.ListChangedFilesForJob(jobId, sessionCode);
                            foreach (string file in changedFiles)
                            {
                                Console.WriteLine("Downloading file: " + file);
                                FileInfo fi = new FileInfo(@"C:\OutputFiles\" + file);
                                scpClient.Download(ft.sharedBasepath + "//" + file, fi);
                            }
                        }
                    }
                    wsFileTransfer.EndFileTransfer(jobId, ft, sessionCode);
                }
                else if (submittedJob.state == JobStateExt.Failed || submittedJob.state == JobStateExt.Canceled) //job failed or was canceled
                {
                    //do nothing
                }
    
                Console.WriteLine("Deleting job folder ...");
                //wsJobManagement.DeleteJob(jobId, sessionCode);
                Console.WriteLine("Job folder was deleted");
            }
    
            private static DigitalSignatureCredentialsExt SignCredentials(DigitalSignatureCredentialsExt creds, string privateKey)
            {
                using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048))
                {
                    rsa.PersistKeyInCsp = false;
                    rsa.FromXmlString(privateKey);
    
                    int val = (Encoding.UTF8.GetBytes(creds.noise)[0]) % creds.noise.Length;
                    StringBuilder sb = new StringBuilder(creds.noise);
                    sb.Insert(val, creds.username);
    
                    byte[] hash;
                    using (SHA256 hashAlg = SHA256.Create())
                    {
                        hash = hashAlg.ComputeHash(Encoding.UTF8.GetBytes(sb.ToString()));
                    }
    
                    var rsaFormatter = new RSAPKCS1SignatureFormatter(rsa);
                    rsaFormatter.SetHashAlgorithm("SHA256");
    
                    sbyte[] signatureBytes = Array.ConvertAll(rsaFormatter.CreateSignature(hash), b => unchecked((sbyte)b));
                    creds.digitalSignature = signatureBytes;
                }
                return creds;
            }
    
            private static string GetRandomString()
            {
                var random = new byte[16];
                var rng = new RNGCryptoServiceProvider();
                rng.GetNonZeroBytes(random);
                return Convert.ToBase64String(random);
            }
    
            private static void AuthenticateUserCredentials()
            {
                Console.WriteLine("Authenticating user [{0}]...", TEST_USER);
                DigitalSignatureCredentialsExt credentials = new DigitalSignatureCredentialsExt();
                credentials.username = TEST_USER;
                credentials.noise = GetRandomString();
                // Sign credentials with known private key
                credentials = SignCredentials(credentials, TEST_USER_PRIVATE_KEY);
                sessionCode = wsUserAndLimitationManagement.AuthenticateUserDigitalSignature(credentials);
                Console.WriteLine("\tAuth OK (Session GUID: {0})", sessionCode);
            }
    
            private static void AuthenticateUserPassword()
            {
                //certificate ssl validation exception
                ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
    
                PasswordCredentialsExt credentials = new PasswordCredentialsExt();
                credentials.username = "[testuser]";
                credentials.password = "[testpass]";
                Console.WriteLine("Authenticating user [{0}]...", credentials.username);
    
                sessionCode = wsUserAndLimitationManagement.AuthenticateUserPassword(credentials);
                Console.WriteLine("\tAuth OK (Session GUID: {0})", sessionCode);
            }
    
            private static void ListAvailableClusters()
            {
                Console.WriteLine("ListAvailableClusters ...");
                ClusterInfoExt[] list = wsClusterInformation.ListAvailableClusters();
                foreach (ClusterInfoExt ci in list)
                {
                    Console.WriteLine(ci.name);
                }
            }
    
            private static void ListJobTemplates()
            {
                ClusterInfoExt[] list = wsClusterInformation.ListAvailableClusters();
                foreach (var cluster in list)
                {
                    Console.WriteLine("Available job templates for {0}", cluster.name);
                    foreach (var nodeType in cluster.nodeTypes)
                    {
                        if (nodeType.possibleCommands.Length < 1)
                            continue;
                        Console.Write("\n\tNode type: {0}\n\tID\tName\t\t\n\n", nodeType.name);
                        foreach (var command in nodeType.possibleCommands)
                        {
                            Console.WriteLine("\t{0}\t{1}\t\t", command.id, command.name, command.code);
                        }
                    }
                }
            }
        }
    }