From ca820733d9cc918e04891e49df15115c1066ae48 Mon Sep 17 00:00:00 2001
From: Brian Wandell <wandell@stanford.edu>
Date: Mon, 23 Oct 2017 10:05:23 -0700
Subject: [PATCH] Rearranging for ultimate separation of cloud control.  Added
 functionality for Alicloud.

---
 Alicloud/aclRootPath.m | 17 ++++++++
 acloud/acloud.m        | 91 ++++++++++++++++++++++++++++++++----------
 gcloud/gcloud.m        | 55 -------------------------
 gcloud/kubernetes.m    | 40 -------------------
 4 files changed, 86 insertions(+), 117 deletions(-)
 create mode 100644 Alicloud/aclRootPath.m
 delete mode 100644 gcloud/gcloud.m
 delete mode 100644 gcloud/kubernetes.m

diff --git a/Alicloud/aclRootPath.m b/Alicloud/aclRootPath.m
new file mode 100644
index 0000000..1d8b61e
--- /dev/null
+++ b/Alicloud/aclRootPath.m
@@ -0,0 +1,17 @@
+function rootPath=aclRootPath()
+%%isetbioRootPath   Return the path to the root isetbio directory
+%
+% Syntax:
+%    rootPath=aclRootPath;
+%
+% Description:
+%    This points at the top level of the acloud tree on the Matlab path.
+%    
+
+%% Get path to this function and then walk back up to the isetbio root.
+pathToMe = mfilename('fullpath');
+
+%% Walk back up the chain
+rootPath = fileparts(pathToMe);
+
+end
diff --git a/acloud/acloud.m b/acloud/acloud.m
index 3b35e3f..f7225b0 100644
--- a/acloud/acloud.m
+++ b/acloud/acloud.m
@@ -6,18 +6,41 @@ classdef acloud < handle
     %
     % ZL Vistasoft Team 2017
     properties 
-        bucket = 'oss://';
-        ros = 'python /Library/Frameworks/Python.framework/Versions/2.7/bin/ros --json';
+        bucket;
+        ros;             % 'python /Library/Frameworks/Python.framework/Versions/2.7/bin/ros --json';
+        kubeTemplate;    % Template for the kubernetes cluster
+        python;          % Many people have two versions of python. This is the executable you want used for alicloud.
     end
     methods
         function obj = acloud(varargin)
-%             p = inputParser;
-%             p.addParameter('bucket','oss://',@ischar);
-%             p.addParameter('ros','python /Library/Frameworks/Python.framework/Versions/2.7/bin/ros --json',@ischar)
-%             p.parse(varargin{:});
-%             obj.bucket = p.Results.bucket;
-%             obj.ros = p.Results.ros;
+            % Users may vary in the version of python, ossutil, ros, and template
+            % locations.  So we let them be set here.
+            %
+            % acloud('python','/Users/wandell/anaconda/bin/python')
+            % 
+            p = inputParser;
+            p.addParameter('bucket','oss://',@ischar);
+            
+            [~,systemPython] = system('which python');
+            p.addParameter('python',systemPython,@(x)(exist(x,'file')));
+            
+            kubeTemplate = fullfile(aclRootPath,'kube_3master.json');
+            p.addParameter('kubeTemplate',kubeTemplate,@(x)(exist(x,'file')));
+
+            p.parse(varargin{:});
+
+            % ROS is in the python bin directory.  We force the output
+            % to be JSON.
+            obj.bucket = p.Results.bucket;            
+            obj.kubeTemplate = p.Results.kubeTemplate;
+            obj.python = p.Results.python;
+                        
+            pythonDir = fileparts(obj.python);
+            obj.ros = fullfile(pythonDir,'ros --json');
+            
         end
+        
+        % List the objects
         function [result, status, cmd] = ls(obj,bucketname)
             if ieNotDefined('bucketname')
                 d = obj.bucket;
@@ -27,6 +50,8 @@ classdef acloud < handle
             cmd = sprintf('ossutil ls %s\n',d);
             [status,result] = system(cmd);
         end
+        
+        % Remove one object
         function [result, status, cmd] = objectrm(obj,objectname)
             if ieNotDefined('objectname')
                 disp('Object name required')
@@ -36,6 +61,8 @@ classdef acloud < handle
                 [status, result] = system(cmd);
             end
         end
+        
+        % Remove one bucket
         function [result, status, cmd] = bucketrm(obj,bucketname)
             if ieNotDefined('bucketname')
                 disp('Bucket name required')
@@ -45,6 +72,8 @@ classdef acloud < handle
                 [status, result] = system(cmd);
             end
         end
+        
+        % Create one bucket
         function [result, status, cmd] = bucketCreate(obj,bucketname)
             if ieNotDefined('bucketname')
                 disp('Bucket name (lower case) required')
@@ -55,48 +84,66 @@ classdef acloud < handle
                 [status, result] = system(cmd);
             end
         end
+        
+        % Upload a folder or a file
         function [result, status, cmd] = upload(obj,local_dir,cloud_dir)
             cloud_dir = fullfile(obj.bucket,cloud_dir);
             cmd = sprintf('ossutil cp %s %s -r -f -u\n',local_dir,cloud_dir);
             [status, result] = system(cmd);
         end
+        
+        % Download a folder or a file
         function [result, status, cmd] = download(obj,cloud_dir,local_dir)
             cloud_dir = fullfile(obj.bucket,cloud_dir);
             cmd = sprintf('ossutil cp %s %s -r -f -u\n',cloud_dir,local_dir);
             [status, result] = system(cmd);
         end
-        function [result, status,masterIp, stackname ,stackID, cmd] = k8sCreate(obj,stackname, MasterInstanceType,WorkerInstanceType,NumberOfNodes,password)
+        
+        % Create a kubernetes cluster that can be controled by kubectl
+        function [result, status,masterIp, stackname ,stackID, cmd] = ...
+                k8sCreate(obj,stackname, MasterInstanceType,WorkerInstanceType,NumberOfNodes,password)
+            
             cmd = sprintf('%s create-stack --stack-name %s --template-url /Users/eugeneliu/git_repo/RenderToolbox4/Alicloud/kube_3master.json --parameters MasterInstanceType=%s,WorkerInstanceType=%s,ImageId=centos_7,NumOfNodes=%d,LoginPassword=%s',...
                 obj.ros,stackname,MasterInstanceType,WorkerInstanceType,NumberOfNodes,password);
+            
             [~, result] = system(cmd);
             result = erase(result,'[Succeed]');
             result = parse_json(result);
             stackID = result.Id;
-            while 1 
-                    cmd = sprintf('%s describe-stack --stack-name %s --stack-id %s',obj.ros,stackname,stackID);
-                    [~, result] = system(cmd);
-                    result_check = erase(result,'[Succeed]');
-                    result_check = parse_json(result_check);
-                    status = result_check.Status;
-                    pause(60);
-                    fprintf('%s\n',status);
-              if strcmp(status,'CREATE_COMPLETE')== 1
-              break;
-              end
-              masterIp = result_check.Outputs{2}.OutputValue;
-            end
             
+            while true
+                % Loop to check the status of the creation.  Return
+                % when done.
+                cmd = sprintf('%s describe-stack --stack-name %s --stack-id %s',obj.ros,stackname,stackID);
+                [~, result] = system(cmd);
+                result_check = erase(result,'[Succeed]');
+                result_check = parse_json(result_check);
+                status = result_check.Status;
+                
+                % Check again in 60 secs
+                pause(60);
+                fprintf('%s\n',status);
+                if strcmp(status,'CREATE_COMPLETE')== 1
+                    break;
+                end
+                masterIp = result_check.Outputs{2}.OutputValue;
+            end
             
         end
+        
+        % Delete a kubernetes cluster
         function[result, status, cmd]= k8sDelete(obj,stackname,stackID)
                 cmd = sprintf('%s delete-stack --region-id us-west-1 --stack-name %s --stack-id %s',obj.ros,stackname,stackID);
                 [status, result] = system(cmd);
         end
+        
+        % Adjust the kubernetes allocation
         function[result, status, cmd]=k8sUpdate(obj,stackname,stackID,MasterInstanceType,WorkerInstanceType,NumberOfNodes,password)
                 cmd = sprintf('%s create-stack --stack-name %s --template-url /Users/eugeneliu/git_repo/RenderToolbox4/Alicloud/kube_3master.json --parameters MasterInstanceType=%s,WorkerInstanceType=%s,ImageId=centos_7,NumOfNodes=%d,LoginPassword=%s,--regionID us-west-1 --stack-id %s',...
                 obj.ros,stackname,MasterInstanceType,WorkerInstanceType,NumberOfNodes,password,stackID); 
                 [status, result] = system(cmd);
         end
+        
     end
 end
 
diff --git a/gcloud/gcloud.m b/gcloud/gcloud.m
deleted file mode 100644
index 647fe83..0000000
--- a/gcloud/gcloud.m
+++ /dev/null
@@ -1,55 +0,0 @@
-classdef gcloud < handle
-    %
-    %  gcloud(command,varargin)
-    %
-    %  ls: @gcloud('ls','directory')
-    %  rm: @gcloud('rm','fullpath to file')
-    %e
-    
-    properties
-        bucket = '';
-    end
-    
-    methods
-        function obj = gcloud(varargin)
-            p = inputParser;
-            p.addParameter('bucket','gs://primal-surfer-140120.appspot.com/',@ischar);
-            
-            p.parse(varargin{:});
-            
-            obj.bucket = p.Results.bucket;
-        end
-        
-        function [result, status] = ls(obj,directory)
-            if ieNotDefined('directory');
-                d = obj.bucket;
-            else
-                d = fullfile(obj.bucket, directory);
-            end
-            
-            cmd = sprintf('gsutil ls %s\n',d);
-            [status,result] = system(cmd);
-            result1 = textscan(result,'%s','Delimiter','\n','CollectOutput',true);
-            result = result1{1};
-            if strncmp(result{1},'CommandException',7)
-                disp(result{1})
-                return;
-            else
-                nFiles = size(result,1);
-                nSkip = length(obj.bucket);
-                for ii=1:nFiles
-                    result{ii} = result{ii}((nSkip+1):end);
-                end
-            end
-            
-        end
-        
-        function [result,status] = rm(obj,fname)
-            %
-            filename = fullfile(obj.bucket, fname);
-            cmd = sprintf('gsutil rm %s\n',filename);
-            [status,result] = system(cmd);
-        end
-        
-    end
-end
diff --git a/gcloud/kubernetes.m b/gcloud/kubernetes.m
deleted file mode 100644
index 38bb835..0000000
--- a/gcloud/kubernetes.m
+++ /dev/null
@@ -1,40 +0,0 @@
-classdef kubernetes < handle
-    % Interface to remember different kubernetes (kubectl) commands
-    %
-    properties
-     
-        % User's name space.  Set when the object is created.
-        namespace = '';
-        
-    end
-    
-    methods
-        function obj = kubernetes(namespace,varargin)
-            p = inputParser;
-            p.addRequired('namespace',@ischar);
-            p.parse(namespace,varargin{:});
-            
-            obj.namespace = p.Results.namespace;
-            
-        end
-        
-        % List the jobs running in your name space
-        function [result,status] = jobs(obj,varargin)
-            
-            p = inputParser;
-            p.addParameter('recipeName','*',@ischar);
-            p.parse(varargin{:});
-            recipeName = p.Results.recipeName;
-            % Could also add 'recipeName' and grep on that
-            if recipeName == '*'
-                cmd = sprintf('kubectl get jobs --namespace=%s',obj.namespace);
-            else
-                cmd = sprintf('kubectl get jobs --namespace=%s | grep %s',obj.namespace,recipeName);
-            end
-            
-            % cmd = sprintf('kubectl get jobs --namespace=%s | grep %s',obj.namespace,recipeName);
-            [status, result] = system(cmd);
-        end
-        
-    end
-end
-- 
GitLab