示例#1
0
        public void WhenPathIsNull_ShouldReturnNull( )
        {
            var fixture = new Fixture( );
            var result  = LinuxPath.GetFileName(null);

            Assert.Null(result);
        }
示例#2
0
        public void SyncServicePullFileTest()
        {
            Device             device             = GetFirstDevice();
            FileListingService fileListingService = new FileListingService(device);

            using (ISyncService sync = device.SyncService)
            {
                String    rfile  = "/sdcard/bootanimations/bootanimation-cm.zip";
                FileEntry rentry = fileListingService.FindFileEntry(rfile);

                String     lpath  = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
                String     lfile  = Path.Combine(lpath, LinuxPath.GetFileName(rfile));
                FileInfo   lfi    = new FileInfo(lfile);
                SyncResult result = sync.PullFile(rfile, lfile, new FileSyncProgressMonitor());

                Assert.IsTrue(lfi.Exists);
                Assert.IsTrue(ErrorCodeHelper.RESULT_OK == result.Code, ErrorCodeHelper.ErrorCodeToString(result.Code));
                lfi.Delete();

                result = sync.PullFile(rentry, lfile, new FileSyncProgressMonitor());
                Assert.IsTrue(lfi.Exists);
                Assert.IsTrue(ErrorCodeHelper.RESULT_OK == result.Code, ErrorCodeHelper.ErrorCodeToString(result.Code));
                lfi.Delete();
            }
        }
示例#3
0
        public void WhenPathIsDirectory_ShouldReturnEmpty( )
        {
            var fixture = new Fixture( );
            var p1      = fixture.Create("/path1-");
            var p2      = "{0}/".With(fixture.Create("path2-"));
            var p       = LinuxPath.Combine(p1, p2);
            var result  = LinuxPath.GetFileName(p);

            Assert.Equal(string.Empty, result);
        }
示例#4
0
        public void WhenPathIsFileWithoutExtension_ShouldReturnFileWithoutExtension( )
        {
            var fixture = new Fixture( );
            var p1      = fixture.Create("/path1-");
            var p2      = "{0}/".With(fixture.Create("path2-"));
            var f       = "{0}".With(fixture.Create("file-"));
            var p       = LinuxPath.Combine(p1, p2, f);
            var result  = LinuxPath.GetFileName(p);

            Assert.Equal(f, result);
        }
示例#5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="FileEntry"/> class.
        /// </summary>
        /// <param name="device">The device.</param>
        /// <param name="path">The path.</param>
        internal FileEntry(Device device, string path)
        {
            this.FetchTime = 0;
            this.Parent    = null;
            bool isDir = path.EndsWith(new string(LinuxPath.DirectorySeparatorChar, 1));

            this.Name     = isDir ? LinuxPath.GetDirectoryName(path) : LinuxPath.GetFileName(path);
            this.IsRoot   = path.Length == 1 && path[0] == LinuxPath.DirectorySeparatorChar;
            this.Type     = isDir ? FileListingService.FileTypes.Directory : FileListingService.FileTypes.File;
            this.Size     = 0;
            this.Children = new List <FileEntry>();
            this.Exists   = false;
            this.Device   = device;
        }
示例#6
0
        public void GetFileNameTest()
        {
            String result = LinuxPath.GetFileName("/system/busybox");

            Assert.AreEqual <string>("busybox", result);

            result = LinuxPath.GetFileName("/");
            Assert.AreEqual <string>("", result);

            result = LinuxPath.GetFileName("/system/xbin/");
            Assert.AreEqual <string>("", result);

            result = LinuxPath.GetFileName("/system/xbin/file.ext");
            Assert.AreEqual <string>("file.ext", result);
        }
示例#7
0
        public void WhenPathContainsInvalidCharacter_ShouldThrowArgumentException( )
        {
            var fixture    = new Fixture( );
            int errorCount = 0;

            for (var x = 0; x < LinuxPathConsts.InvalidPathChars.Length; ++x)
            {
                try {
                    string result = LinuxPath.GetFileName("/some/path/{0}-{1}.ext".With(LinuxPathConsts.InvalidPathChars[x], fixture.Create("file-")));
                } catch (ArgumentException) {
                    errorCount++;
                }
            }

            Assert.Equal(LinuxPathConsts.InvalidPathChars.Length, errorCount);
        }
示例#8
0
        /// <summary>
        /// <para>
        /// Handles the cleanup of tasks targeting the current cluster node:
        /// </para>
        /// <list type="bullet">
        /// <item>
        /// Tasks whose <see cref="V1NeonNodeTask.TaskStatus.AgentId"/> doesn't match
        /// the ID for the current agent will be marked as <see cref="V1NeonNodeTask.Phase.Orphaned"/>
        /// and the finish time will be set to now.  This sets the task up for eventual
        /// deletion.
        /// </item>
        /// <item>
        /// Tasks with a finish time that is older than <see cref="V1NeonNodeTask.TaskSpec.RetentionTime"/>
        /// will be removed.
        /// </item>
        /// <item>
        /// Scheduled tasks that missed their scheduling window will be marked as TARDY and
        /// will be retained for a while before being deleted.
        /// </item>
        /// </list>
        /// </summary>
        /// <returns>The tracking <see cref="Task"/>.</returns>
        private async Task CleanupTasksAsync()
        {
            var utcNow    = DateTime.UtcNow;
            var nodeTasks = (await k8s.ListClusterCustomObjectAsync <V1NeonNodeTask>()).Items
                            .Where(tasks => NodeTaskFilter(tasks))
                            .ToArray();

            foreach (var nodeTask in nodeTasks)
            {
                var taskName = nodeTask.Name();

                //-------------------------------------------------------------
                // Remove invalid tasks.

                try
                {
                    nodeTask.Validate();
                }
                catch (Exception e)
                {
                    log.LogWarn($"Invalid NodeTask: [{taskName}]", e);
                    log.LogWarn($"Deleting invalid NodeTask: [{taskName}]");
                    await k8s.DeleteClusterCustomObjectAsync(nodeTask);

                    continue;
                }

                if (nodeTask.Status.Phase == V1NeonNodeTask.Phase.Running)
                {
                    //---------------------------------------------------------
                    // Detect and kill orphaned tasks.

                    if (nodeTask.Status.AgentId != Node.AgentId)
                    {
                        log.LogWarn($"Detected orphaned [nodetask={taskName}]: task [agentID={nodeTask.Status.AgentId}] does not match operator [agentID={Node.AgentId}]");

                        // Update the node task status to: ORPHANED

                        var patch = OperatorHelper.CreatePatch <V1NeonNodeTask>();

                        patch.Replace(path => path.Status.Phase, V1NeonNodeTask.Phase.Orphaned);
                        patch.Replace(path => path.Status.FinishTimestamp, utcNow);
                        patch.Replace(path => path.Status.ExitCode, -1);

                        await k8s.PatchClusterCustomObjectStatusAsync <V1NeonNodeTask>(OperatorHelper.ToV1Patch <V1NeonNodeTask>(patch), nodeTask.Name());

                        await KillTaskAsync(nodeTask);

                        continue;
                    }

                    //---------------------------------------------------------
                    // Kill tasks that have been running for too long.

                    if (nodeTask.Status.Phase == V1NeonNodeTask.Phase.Running &&
                        utcNow - nodeTask.Status.StartTimestamp >= TimeSpan.FromSeconds(nodeTask.Spec.TimeoutSeconds))
                    {
                        log.LogWarn($"Execution timeout [nodetask={taskName}]: execution time exceeds [{nodeTask.Spec.TimeoutSeconds}].");
                        await KillTaskAsync(nodeTask);

                        // Update the node task status to: TIMEOUT

                        var patch = OperatorHelper.CreatePatch <V1NeonNodeTask>();

                        patch.Replace(path => path.Status.Phase, V1NeonNodeTask.Phase.Timeout);
                        patch.Replace(path => path.Status.FinishTimestamp, utcNow);
                        patch.Replace(path => path.Status.RuntimeSeconds, (int)Math.Ceiling((utcNow - nodeTask.Status.StartTimestamp.Value).TotalSeconds));
                        patch.Replace(path => path.Status.ExitCode, -1);

                        await k8s.PatchClusterCustomObjectStatusAsync <V1NeonNodeTask>(OperatorHelper.ToV1Patch <V1NeonNodeTask>(patch), nodeTask.Name());

                        continue;
                    }

                    //---------------------------------------------------------
                    // Detect that missed their scheduling window and mark them as tardy

                    if (nodeTask.Status.Phase == V1NeonNodeTask.Phase.Pending &&
                        nodeTask.Spec.StartBeforeTimestamp.HasValue && nodeTask.Spec.StartBeforeTimestamp <= utcNow)
                    {
                        log.LogWarn($"Detected tardy [nodetask={taskName}]: task execution didn't start before [{nodeTask.Spec.StartBeforeTimestamp}].");

                        // Update the node task status to: TARDY

                        var patch = OperatorHelper.CreatePatch <V1NeonNodeTask>();

                        patch.Replace(path => path.Status.Phase, V1NeonNodeTask.Phase.Tardy);
                        patch.Replace(path => path.Status.FinishTimestamp, utcNow);
                        patch.Replace(path => path.Status.ExitCode, -1);

                        await k8s.PatchClusterCustomObjectStatusAsync <V1NeonNodeTask>(OperatorHelper.ToV1Patch <V1NeonNodeTask>(patch), nodeTask.Name());

                        continue;
                    }
                }
            }

            //-----------------------------------------------------------------
            // Remove tasks that have been retained long enough.

            foreach (var nodeTask in nodeTasks
                     .Where(task => task.Status.Phase != V1NeonNodeTask.Phase.New && task.Status.Phase != V1NeonNodeTask.Phase.Running)
                     .Where(task => (utcNow - task.Status.FinishTimestamp) >= TimeSpan.FromSeconds(task.Spec.RetentionSeconds)))
            {
                log.LogWarn($"[nodetask={nodeTask.Name()}]: has been retained for [{nodeTask.Spec.RetentionSeconds}] (deleting now).");
                await k8s.DeleteClusterCustomObjectAsync(nodeTask);
            }

            //-----------------------------------------------------------------
            // Remove any script folders whose node task no longer exists.

            if (NeonHelper.IsLinux)
            {
                var nodeTaskExecuteIds = new HashSet <string>();

                foreach (var nodeTask in nodeTasks.Where(task => !string.IsNullOrEmpty(task.Status.RunId)))
                {
                    nodeTaskExecuteIds.Add(nodeTask.Status.RunId);
                }

                foreach (var scriptFolderPath in Directory.GetDirectories(hostNeonTasksFolder, "*", SearchOption.TopDirectoryOnly))
                {
                    var scriptFolderName = LinuxPath.GetFileName(scriptFolderPath);

                    if (!nodeTaskExecuteIds.Contains(scriptFolderName))
                    {
                        log.LogWarn($"Removing node task host script folder: {scriptFolderName}");
                        NeonHelper.DeleteFolder(scriptFolderPath);
                    }
                }
            }
        }
示例#9
0
 public void GetFileName()
 {
     Assert.Equal("three.txt", LinuxPath.GetFileName("\\one\\two\\three.txt"));
     Assert.Equal("three.txt", LinuxPath.GetFileName("/one/two/three.txt"));
 }