\documentclass[english,serif,mathserif,xcolor=pdftex,dvipsnames,table]{beamer}
\usepackage{lsci}

\title[ARClib]{%
  Introduction to ARClib
  with~Python
}
\author[R. Murri]{%
  \textbf{Riccardo Murri} \\
  Grid Computing Competence Center, \\
  Organisch-Chemisches Institut, \\
  University of Zurich
}
\date{Nov.~10,~2011}

% for typesetting "C++", see
% http://stackoverflow.com/questions/2724760/how-to-write-c-in-latex
\usepackage{relsize}
\newcommand\ifmonospace{%
  \ifdim\fontdimen3\font=0pt%
}
\newcommand\Cpp{%
  \ifmonospace%
  C++%
  \else%
  C\kern-.0667em\raise.20ex\hbox{\relsize{-2}{++}}%
  \fi%
  \spacefactor1000%
}


\begin{document}

% title frame
\maketitle


\section{Introduction}

\begin{frame}
  \frametitle{Today's class}
  
  An introduction to using ARClib from Python.

  \+
  Or how to re-implement the
  \texttt{arcsub}/\texttt{arcstat}/\texttt{arcget} 
  commands using Python and good will.

  \+
  {\small These slides are available for download from: 
    \url{http://www.gc3.uzh.ch/teaching/lsci2011/lab08.pdf}}
\end{frame}

\begin{frame}
  \frametitle{What is ARClib?}
  A \Cpp{} library, the core of the ARC middleware clients.

  \+
  The \texttt{arcsub}/\texttt{arcstat}/\texttt{arcget}/etc. commands
  are basically command-line wrappers around ARClib library calls.

\end{frame}


\begin{frame}
  \frametitle{ARC1 vs ARC0}
  
  ARC1 is the current version of the ARC middleware.

  \+
  ARC0 is the older version, currently unsupported upstream.

  \+
  ARC1 has Python and Java bindings.

  \+
  ARC0 has Python and PERL bindings.
\end{frame}


\begin{frame}
  \frametitle{Tough luck}

  However, some design flaws prevent the use of ARC1 in languages
  with automated garbage collection.

  \+
  So we're going to use ARC0. 
  (But is simpler, by the way).

\end{frame}


\begin{frame}[fragile]
  The ARC0 Python library is included in package
  \texttt{nordugrid-arc-compat}, which you should have already
  installed.

  \+
  To start using it from Python, import the \texttt{arclib} module:
  \begin{python}
  >>>  import arclib
  \end{python}

  \+
  The official API documentation (\Cpp{} and Python) is available at:
  \url{http://svn.nordugrid.org/trac/nordugrid/browser/arc0/tags/0.8.3/doc/arclib/arclib.pdf}
\end{frame}

\section{whoami}

\begin{frame}
  \frametitle{Managing certificates and proxies}
  % ARClib only offers functions for \emph{checking} if a certificate or
  % Grid proxy exists, and extracting minimal information from it.

  \begin{describe}{%
      \lstinline|arclib.Certificate()|, 
      \lstinline|arclib.Certificate(arclib.PROXY)|}
    Constructors: create an object for inspecting a certificate/proxy.
    Raise \lstinline|arclib.CertificateError| if the certificate/proxy
    is not readable or the file is corrupted.
  \end{describe}

  \begin{describe}{\lstinline|GetCertFilename()| 
      {\small (method on \lstinline|Certificate| instances)}}
    Return the path to the file containing the certificate/proxy.
  \end{describe}

  \begin{describe}{\lstinline|IsExpired()| 
      {\small (method on \lstinline|Certificate| instances)}}
    Return \lstinline|True| if the certificate/proxy is no longer valid.
  \end{describe}

  \begin{describe}{\lstinline|GetSN()| 
      {\small (method on \lstinline|Certificate| instances)}}
    Return the ``Subject DN'' stored in the cert./proxy.
  \end{describe}
\end{frame}


\begin{frame}
  \begin{exercise}
    Write a \lstinline|gridauth| module, containing a
    \lstinline|GridAuth| class with the following behavior:
    \begin{itemize}
    \item The \lstinline|GridAuth| constructor shall take no arguments;
    \item A \lstinline|GridAuth| instance shall be successfully constructed
      iff \emph{both} a certificate \emph{and} a proxy exist and are valid;
    \item If the certificate does not exist, the \lstinline|GridAuth|
      constructor shall raise a \lstinline|gridauth.NoCertificate|
      exception; if it exists but is expired, the \lstinline|GridAuth|
      constructor shall raise a
      \lstinline|gridauth.ExpiredCertificate| exception;
    \item Similarly with the proxy, using exceptions
      \lstinline|gridauth.NoProxy| and \lstinline|gridauth.ExpiredProxy|;
    \item The ``Subject DN'' of the certificate shall be available on
      a \lstinline|GridAuth| object as instance attribute \lstinline|DN|.
    \end{itemize}
  \end{exercise}
\end{frame}


\begin{frame}
  \begin{exercise}
    Write a program \texttt{whoami.py}:
    \begin{itemize}
    \item If a valid certificate and proxy exist, running the program
      prints the ``Subject DN'' of the certificate and exits with code 0.
    \item If no certificate exists, or it is expired, the program
      exists with an appropriate error message.
    \item Similarly exists with an error message if the proxy does not
      exist or is expired.
    \item Each of the four error conditions above should use a
      different nonzero exit code.
    \end{itemize}
  \end{exercise}
\end{frame}


\section{arcstat}

\begin{frame}
  \frametitle{Contacting the GIIS}
  ARC uses a central information ``index'' (more on this in next
  lecture), accessible over the \href{http://en.wikipedia.org/wiki/Ldap}{LDAP protocol}.

  \+
  To gather information about any entity in the Grid (cluster, job,
  user), you contact this information index (called the GIIS).

  \+
  The GIIS of the SMSCG infrastructure can be contacted at the URL
  {\small \url{ldap://giis.smscg.ch:2135/o=grid/mds-vo-name=switzerland}}
\end{frame}


\begin{frame}[fragile]
  \frametitle{ARClib does URLs}
  ARClib provides its own facility for (Grid) URL handling.

  \+
  Create an ARClib URL object:
  \begin{lstlisting}[basicstyle=\footnotesize\ttfamily]
>>> giis_url = arclib.URL('ldap://giis.smscg.ch:2135'
...                       '/o=grid/mds-vo-name=switzerland')
  \end{lstlisting}

  \+
  The logical parts of the URL are available thorugh accessor method
  calls:
  \begin{lstlisting}[basicstyle=\footnotesize\ttfamily]
>>> giis_url.CanonicalURL()
'ldap://giis.smscg.ch:2135/o=grid/mds-vo-name=switzerland'
>>> giis_url.Host()
'giis.smscg.ch'
>>> giis_url.Port()
2135
>>> giis_url.BaseDN()
'mds-vo-name=switzerland, o=grid'
  \end{lstlisting}
\end{frame}


\begin{frame}[fragile]
  \frametitle{Listing resources}
  Listing available computing resources is simple:
  \begin{python}
>>> clusters = arclib.GetClusterResources(giis_url)
  \end{python}

  \+
  The returned value is a tuple of \lstinline|arclib.URL| objects:
  \begin{python}
>>> clusters
(<arclib.URL; ... >, <arclib.URL; proxy of <Swig Object of type 'URL *' ...> >, ...
>>> type(clusters)
<type 'tuple'>
>>> type(clusters[0])
<class 'arclib.URL'>
  \end{python}

  \+
  \begin{exercise}
    Write a function \lstinline|list_clusters(url)| that returns the
    list of Internet host names of all the clusters registered at the
    given GIIS URL.  Assume the \lstinline|url| argument is a string.
  \end{exercise}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Listing jobs on a cluster}
  The following functions in ARClib allow you to retrieve information
  on jobs running on a remote cluster.

  \begin{describe}{\lstinline|arclib.GetClusterJobs(cluster)|}
    Return a sequence of \lstinline|arclib.Job| objects, one for each
    job that is currently managed by the remote cluster.  The sole
    argument \lstinline|cluster| is a \lstinline|arclib.URL| instance
    pointing to a cluster (as returned by
    \lstinline|arclib.GetClusterResources|). 
  \end{describe}

  \begin{describe}{\lstinline|arclib.GetClusterJobs(cluster_list)|}
    Same as above, but the argument is a \lstinline|list| of cluster URLs.
  \end{describe}
\end{frame}

\begin{frame}[fragile,fragile]
  \frametitle{What's a Job like, anyway?}
\begin{lstlisting}[basicstyle=\scriptsize\ttfamily]
>>> jobs = arclib.GetClusterJobs(cluster)
>>> job = jobs[0]
\end{lstlisting}
  As usual, we can use \lstinline|dir()| to inspect live objects:
  \begin{lstlisting}[basicstyle=\scriptsize\ttfamily]
>>> dir(job)
[!\ldots!, 'cluster', 'comment', 'completion_time', 'cpu_count',
'erase_time', 'errors', 'execution_nodes', 'exitcode', 'gmlog', 
'id', 'job_name', 'mds_validfrom', 'mds_validto', 'owner', 
'proxy_expire_time', 'queue', 'queue_rank', 'requested_cpu_time', 
'requested_wall_time', 'rerunable', 'runtime_environments', 
'sstderr', 'sstdin', 'sstdout', 'status', 'submission_time', 
'submission_ui', 'this', 'used_cpu_time', 'used_memory', 'used_wall_time']
>>> job.id
'gsiftp://smscg.inf.usi.ch:2811/jobs/143741321446490878298264'
>>> job.cluster
'smscg.inf.usi.ch'
>>> job.owner
'/DC=com/DC=quovadisglobal/DC=grid/DC=switch/DC=users/C=CH/O=SWITCH/CN=Placi Flury'
>>> job.status
'INLRMS:Q'
  \end{lstlisting}
\end{frame}

% \begin{frame}[fragile]
%   \frametitle{Interlude: emulating \texttt{dict}'s}

%   Any instance \lstinline|x| of a class that defines a 
%   \lstinline|__getitem__(self, key)| method can use dictionary-like
%   lookup syntax \lstinline|x[key]|:
%   \begin{python}
% >>> class MyDict(UserDict.DictMixin):
% ...   def __getitem__(self, key):
% ...     return 42
% >>> x = MyDict()
% >>> x['whatever']
% 42
%   \end{python}

%   \+
%   Inheriting from the standard library class
%   \lstinline|UserDict.DictMixin| is needed to define other
%   dictionary-like methods on top of \lstinline|__getitem__|.
  
%   \begin{seealso}
%     {\scriptsize \url{http://docs.python.org/library/userdict.html#module-UserDict}}
%     \hbox{\scriptsize\url{http://docs.python.org/reference/datamodel.html#emulating-container-types}}
%   \end{seealso}
% \end{frame}


% \begin{frame}
%   \begin{exercise}
%     Implement a dictionary-like object \lstinline|JobsByCluster|, mapping
%     cluster names to \lstinline|arclib.Job| objects.
%     \begin{itemize}
%     \item The constructor takes two arguments: a \lstinline|GridAuth|
%       instance, and an optional GIIS URL (a string).  The GIIS URL
%       defaults to the SMSCG one.
%     \item  The \lstinline|Job| objects associated with a cluster name
%       are the jobs registered with the remote cluster owned by the
%       ``Subject DN'' of the \lstinline|GridAuth| passed to the
%       constructor. 
%     \end{itemize}
%   \end{exercise}
% \end{frame}


\begin{frame}[fragile]
  \begin{exercise}
    Implement a program \texttt{joblist.py}:
    \begin{itemize}
    \item If called without command-line arguments, prints a list of
      job names and corresponding job IDs running at all available
      clusters; the cluster name is used as a heading before the job
      IDs assigned to that cluster.  Example:
      \begin{lstlisting}[language=sh]
        $ !\textbf{./joblist.py}!
        === a.cluster.name ===
        name1: job ID 1
        name2: job ID 2
        ....
        === another.cluster.here ===
        name: job ID 
        ....
      \end{lstlisting}
    \item If called with arguments, those argument must be cluster
      names: only the jobs assigned to those clusters must be listed. 
    \end{itemize}
  \end{exercise}
\end{frame}


\end{document}

%%% Local Variables: 
%%% mode: latex
%%% TeX-master: t
%%% End: 

