Muster C++ API Usage

The C++ Muster API is mostly declared inside the MClientLib namespace. The API declares two global structures (MUSTER and MUSTERCLIENT) that are required to hold any connection versus the Dispatcher (MUSTER) and a Render client (MUSTERCLIENT).

The first step required to use the API is including the headers:

#include <muster.h>
#include <MClientLib/MClientLib.h>
#include <MClientLib/MErrors.h>
  • muster.h : This header files at the root level of the SDK includes directory declares some common constants required across the entire Muster codebase.
  • MClientLib/MClientLib.h : This header declares the classes and functions available within the API
  • MClientLib/MErrors.h : This header declares common classes used as return values for the API functions

Before using any function of the API, you must initialize it using:

MClientLib::MUSTERERR err = MClientLib::InitializeLibrary(argv[0]);

The InitializeLibrary() function setup some internal stuff as well as getting the path of the module you're going to execute. It's mostly required by the templates and Python function to find the path to the Muster Python distribution. Alternatively , you can invoke it with MClientLib::InitializeLibrary(0) and it will guess the module path. The path to Muster runtimes can be also specified by declaring the MUSTER environmental variable before launching your executable.
The InitializeLibrary function call returns a MClientLib::MUSTERERR object that's used across the API to return function execution results. You should always check the MUSTERERR object using the getErrorCode() class method against the MERR_ERR_OK constant:

if (err.getErrorCode() != MERR_ERR_OK) {
  fprintf(stderr,"Failure on  MClientLib::InitializeLibrary()\n");
  return -1;
}

Each call to the InitializeLibrary() function must be paired with a MClientLib::ShutdownLibrary() before shutting down your module. This is required to free internal memory allocations and it's mandatory!

After a successful initialisation of the library, you can attempt to establish a connection versus a Dispatcher service or a Render client service. This can be done using the InitializeSession() or InitializeClientSession() functions, that should be followed by a call to the Connect() function:

MClientLib::MUSTER* session = MClientLib::InitializeSession();
printf("\nConnecting to %s...",server);
err = MClientLib::Connect(session,server,nPort);
if (err.getErrorCode() != MERR_ERR_OK) {
  fprintf(stderr,"\nUnable to connect to %s:%d.\n",server,nPort);
  MClientLib::ShutdownSession(session);
  MClientLib::ShutdownLibrary();
  return -1;
}

As you can see from the code, a session must always be deallocated by ShutdownSession() or ShutdownClientSession()

The next step after a successful connection to the Dispatcher service requires the authentication on the Dispatcher:

err = MClientLib::Authenticate(session,username,password);
if (err.getErrorCode() != MERR_ERR_OK) {
  fprintf(stderr,"Authentication failed...\n");
  MClientLib::Disconnect(session);
  MClientLib::ShutdownSession(session);
  MClientLib::ShutdownLibrary();
  return -1;
}
 
MClientLib::MUSTERAUTH authenticationStatus = MClientLib::GetAuthenticationStatus(session);
switch (authenticationStatus.status) {
  case MClientLib::kLoginAdmin:
    printf("Login successfully.\n");
    break;
  case MClientLib::kLoginGuest:
    printf("Logged as guest.\n");
    break;
  case MClientLib::kLoginDeniedLDAPDown:
    printf("Login denied. Directory server is down !");
    MClientLib::Disconnect(session);
    MClientLib::ShutdownSession(session);
    MClientLib::ShutdownLibrary();
    return -1;
    break;
  case MClientLib::kLoginDenied:
    printf("Login denied.\n");
    MClientLib::Disconnect(session);
    MClientLib::ShutdownSession(session);
    MClientLib::ShutdownLibrary();
    return -1;
    break;
  }
 
if (authenticationStatus.ldapByPassed) {
  printf("Directory authentication bypassed. Login from regular Muster users database!\n\n");
}

Once authenticated , you can perform any operation on the Dispatcher nodes and jobs queue using the functions provided by the API.

The rest of the following code shows how to retrieve the server status and print it:

  printf("Requesting status...\n");
  err = MClientLib::AcquireServerStatus(session);
  if (err.getErrorCode() == MERR_ERR_OK) {
    MClientLib::MUSTERSERVER serverStatus = MClientLib::GetServerStatus(session);
    if (serverStatus.networkProtocolVersion != kNetworkProtocolVersion) {
      fprintf(stderr,"\n### Protocol version Mismatch. Expecting %d, received %d!\n\n",kNetworkProtocolVersion,serverStatus.networkProtocolVersion);
    }
  }
 
  MClientLib::Disconnect(session);
  MClientLib::ShutdownSession(session);
  MClientLib::ShutdownLibrary();
}

If you need to perform an operation on a specific job, you can call one of the jobs functions like:

// Pause the job ID 12
err =  MClientLib::JobActionPause (session, 12);
if (err.getErrorCode() != MERR_ERR_OK) {
  fprintf(stderr,"Failed to pause job: %s",err.getDescription().c_str());
}

You can find a complete set of usage examples inside the mrtool source code available inside the SDK.

Compiling on Windows

The compilation on Windows is suggested on Microsoft Visual Studio 2015, that's the platform used to build Muster itself. Even it's supported on any compiler, flags and procedures may change according to your build platform.

Start Visual Studio creating a new solution or project:

Be sure to remove the precompiled headers feature not supported by the Muster API headers:

Configure the path to the includes directory to find the API includes:

Configure the path to the Linker libraries to find the API .libs files:

Configure the additional required libs for the linker:

Remember to copy the Muster runtimes .DLL into your application folder (MClientLib.dll , MTemplate.dll, MBase.dll, MTemplate.dll and MFramework.dll) or alternatively add the Muster installation path to your PATH environmental variable.

Compiling on Linux

Compiling a Muster API source code module on Linux requires you to point g++ on the SDK includes as well as the local Muster installation shared libraries.

For example, assuming you've wrote a mymustercmd.cpp file and your Muster installation is available on /usr/local/muster8 , and your sdk installation at /usr/local/muster8/sdk, you compile your file with:

g++ -I/usr/local/muster8/sdk/includes -L/usr/local/muster8 -lMClientLib -lMBase -lMTemplate -lMFramework mymustercmd.cpp -o ./mymustercmd

The MClientLib, MBase and MTemplate are the minimal shared libraries required to compile a Muster API module.
Be sure also that the module is always able to find the Muster shared libraries, alternatively, you can set your libraries search path and the MUSTER installation path before invoking it:

LD_LIBRARY_PATH=/usr/local/muster8:$LD_LIBRARY_PATH
MUSTER=/usr/local/muster8
export LD_LIBRARY_PATH
export MUSTER
./mymustercmd

Compiling on MAC OS X

Compiling a Muster API source code module on MAC OS X requires you to point g++ on the SDK includes as well as the local Muster installation shared libraries.

For example, assuming you've wrote a mymustercmd.cpp file and your Muster installation is available on /Applications/Muster8 , and your sdk installation at /Applications/Muster8/sdk, you compile your file with:

g++ -I/Applications/Muster8/Contents/sdk/includes -L/Applications/Muster8/Contents/muster8 -lMClientLib -lMBase -lMTemplate -lMFramework mymustercmd.cpp -o ./mymustercmd

The MClientLib, MBase and MTemplate are the minimal shared libraries required to compile a Muster API module.
Be sure also that the module is always able to find the Muster shared libraries, alternatively, you can set your libraries search path and the MUSTER installation path before invoking it:

MUSTER=/Applications/Muster8/Contents
DYLD_LIBRARY_PATH=/Applications/Muster8/Contents/Frameworks:$DYLD_LIBRARY_PATH
export MUSTER
export DYLD_LIBRARY_PATH
./mymustercmd