XAP

Administration API

The Admin API provides a way to administer and monitor all of GigaSpaces services and components using a simple API. The API provides information and the ability to operate on the currently running GigaSpaces Agent, the Manager, the Container, Lookup Service, Processing UnitClosed This is the unit of packaging and deployment in the GigaSpaces Data Grid, and is essentially the main GigaSpaces service. The Processing Unit (PU) itself is typically deployed onto the Service Grid. When a Processing Unit is deployed, a Processing Unit instance is the actual runtime entity., and Spaces.

Dependencies

In order to use this feature, include the $GS_HOME/lib/platform/service-grid/xap-admin.jar file on your classpath or use maven dependencies:

<dependency>
    <groupId>com.gigaspaces</groupId>
    <artifactId>xap-admin</artifactId>
    <version>17.0-m1</version>
</dependency>

For more information on dependencies, refer to Maven Artifacts.

Examples

The following code examples show how the Admin API can be used to display information on the currently deployed services/components:

public void gsa() {
    Admin admin = new AdminFactory().addGroup("myGroup").createAdmin();
    // wait till things get discovered (you can also use specific waitFor)
    for (GridServiceAgent gsa : admin.getGridServiceAgents()) {
        System.out.println("GSAClosed Grid Service Agent.
This is a process manager that can spawn and manage Service Grid processes (Operating System level processes) such as The Grid Service Manager, The Grid Service Container, and The Lookup Service. Typically, the GSA is started with the hosting machine's startup. Using the agent, you can bootstrap the entire cluster very easily, and start and stop additional GSCs, GSMs and lookup services at will. [" + gsa.getUid()
                + "] running on Machine ["
                + gsa.getMachine().getHostAddress());
        for (AgentProcessDetails processDetails : gsa.getProcessesDetails()) {
            System.out.println("   -> Process ["
                    + Arrays.toString(processDetails.getCommand()) + "]");
        }
    }
}
public void gsm() {
    Admin admin = new AdminFactory().addGroup("myGroup").createAdmin();
    // wait till things get discovered (you can also use specific waitFor)
    for (GridServiceManager gsm : admin.getGridServiceManagers()) {
        System.out.println("GSMClosed Grid Service Manager.
This is is a service grid component that manages a set of Grid Service Containers (GSCs). A GSM has an API for deploying/undeploying Processing Units. When a GSM is instructed to deploy a Processing Unit, it finds an appropriate, available GSC and tells that GSC to run an instance of that Processing Unit. It then continuously monitors that Processing Unit instance to verify that it is alive, and that the SLA is not breached. [" + gsm.getUid() + "] running on Machine "
                + gsm.getMachine().getHostAddress());
    }
}
public void gsc() {
    Admin admin = new AdminFactory().addGroup("myGroup").createAdmin();
    // wait till things get discovered (you can also use specific waitFor)
    for (GridServiceContainer gsc : admin.getGridServiceContainers()) {
        System.out.println("GSCClosed Grid Service Container.
This provides an isolated runtime for one (or more) processing unit (PU) instance and exposes its state to the GSM. [" + gsc.getUid() + "] running on Machine "
                + gsc.getMachine().getHostAddress());
        for (ProcessingUnitInstance puInstance : gsc
                .getProcessingUnitInstances()) {
            System.out.println("   -> PUClosed This is the unit of packaging and deployment in the GigaSpaces Data Grid, and is essentially the main GigaSpaces service. The Processing Unit (PU) itself is typically deployed onto the Service Grid. When a Processing Unit is deployed, a Processing Unit instance is the actual runtime entity. [" + puInstance.getName() + "]["
                    + puInstance.getInstanceId() + "]["
                    + puInstance.getBackupId() + "]");
        }
    }
}

public void pu() {
    Admin admin = new AdminFactory().addGroup("myGroup").createAdmin();
    // wait till things get discovered (you can also use specific waitFor)
    for (ProcessingUnit processingUnit : admin.getProcessingUnits()) {
        System.out.println("Processing Unit: " + processingUnit.getName()
                    + " status: " + processingUnit.getStatus());
        if (processingUnit.isManaged()) {
                System.out.println("   -> Managing GSM: "
                        + processingUnit.getManagingGridServiceManager()
                                .getUid());
        } else {
                System.out.println("   -> Managing GSM: NA");
        }

        for (GridServiceManager backupGSM : processingUnit
                    .getBackupGridServiceManagers()) {
                System.out.println("   -> Backup GSM: " + backupGSM.getUid());
        }

        for (ProcessingUnitInstance processingUnitInstance : processingUnit) {
                System.out.println("   ["
                        + processingUnitInstance.getClusterInfo()
                        + "] on GSC ["
                        + processingUnitInstance.getGridServiceContainer()
                                .getUid() + "]");
                if (processingUnitInstance.isEmbeddedSpaces()) {
                    System.out.println("      -> Embedded SpaceClosed Where GigaSpaces data is stored. It is the logical cache that holds data objects in memory and might also hold them in layered in tiering. Data is hosted from multiple SoRs, consolidated as a unified data model. ["
                            + processingUnitInstance.getSpaceInstance()
                                    .getUid() + "]");
                }

                Map<String, ServiceDetails> services = processingUnitInstance.getServiceDetailsByServiceId();

                for (ServiceDetails details : services.values()) {
                    System.out.println("      -> Service " + details);
                }
        }
    }
}

The number of backups — space.getNumberOfBackups() — will be zero or one.


public void space() {
    Admin admin = new AdminFactory().addGroup("myGroup").createAdmin();

    for (Space space : admin.getSpaces()) {
        System.out.println("Space [" + space.getUid()
                    + "] numberOfInstances [" + space.getNumberOfInstances()
                    + "] numberOfbackups [" + space.getNumberOfBackups() + "]");
        System.out.println("  Stats: Write ["
                    + space.getStatistics().getWriteCount() + "/"
                    + space.getStatistics().getWritePerSecond() + "]");
        for (SpaceInstance spaceInstance : space) {
                System.out.println("   -> INSTANCE [" + spaceInstance.getUid()
                        + "] instanceId [" + spaceInstance.getInstanceId()
                        + "] backupId [" + spaceInstance.getBackupId()
                        + "] Mode [" + spaceInstance.getMode() + "]");
                System.out.println("         -> Host: "
                        + spaceInstance.getMachine().getHostAddress());
                System.out.println("         -> Stats: Write ["
                        + spaceInstance.getStatistics().getWriteCount() + "/"
                        + spaceInstance.getStatistics().getWritePerSecond()
                        + "]");
            }
        for (SpacePartition spacePartition : space.getPartitions()) {
                System.out.println("   -> Partition ["
                        + spacePartition.getPartitionId() + "]");
                for (SpaceInstance spaceInstance : spacePartition) {
                    System.out.println("      -> INSTANCE ["
                            + spaceInstance.getUid() + "]");
                }
        }
    }
}
public void virtualMachine() {
    Admin admin = new AdminFactory().addGroup("myGroup").createAdmin();
        // wait till things get discovered (you can also use specific waitFor)
    System.out.println("VM TOTAL STATS: Heap Committed ["
                + admin.getVirtualMachines().getStatistics()
                        .getMemoryHeapCommittedInGB() + "GB]");
    System.out.println("VM TOTAL STATS: GC PERC ["
                + admin.getVirtualMachines().getStatistics()
                        .getGcCollectionPerc()
                + "], Heap Used ["
                + admin.getVirtualMachines().getStatistics()
                        .getMemoryHeapUsedPerc() + "%]");

    for (VirtualMachine virtualMachine : admin.getVirtualMachines()) {
            System.out.println("VM [" + virtualMachine.getUid() + "] "
                    + "Host [" + virtualMachine.getMachine().getHostAddress()
                    + "] " + "GC Perc ["
                    + virtualMachine.getStatistics().getGcCollectionPerc()
                    + "], " + "Heap Usage ["
                    + virtualMachine.getStatistics().getMemoryHeapUsedPerc()
                    + "%]");

            for (ProcessingUnitInstance processingUnitInstance : virtualMachine
                    .getProcessingUnitInstances()) {
                System.out.println("   -> PU ["
                        + processingUnitInstance.getUid() + "]");
            }
            for (SpaceInstance spaceInstance : virtualMachine
                    .getSpaceInstances()) {
                System.out.println("   -> Space [" + spaceInstance.getUid()
                        + "]");
            }
    }
}
public void machine() {
    Admin admin = new AdminFactory().addGroup("myGroup").createAdmin();
        // wait till things get discovered (you can also use specific waitFor)
    for (Machine machine : admin.getMachines()) {
            System.out.println("Machine ["
                    + machine.getUid()
                    + "], "
                    + "TotalPhysicalMem ["
                    + machine.getOperatingSystem().getDetails()
                            .getTotalPhysicalMemorySizeInGB()
                    + "GB], "
                    + "FreePhysicalMem ["
                    + machine.getOperatingSystem().getStatistics()
                            .getFreePhysicalMemorySizeInGB() + "GB]]");

            for (SpaceInstance spaceInstance : machine.getSpaceInstances()) {
                System.out.println("   -> Space [" + spaceInstance.getUid()
                        + "]");
            }
            for (ProcessingUnitInstance processingUnitInstance : machine
                    .getProcessingUnitInstances()) {
                System.out.println("   -> PU ["
                        + processingUnitInstance.getUid() + "]");
            }
    }
}

Obtaining information about the currently deployed services/components via the started GridServiceAgents:

    public void findStartedGridServiceContainers() {
        Admin admin = new AdminFactory().createAdmin();

        // wait at least for one agent
        admin.getGridServiceAgents().waitForAtLeastOne();

        for (GridServiceAgent gsa : admin.getGridServiceAgents()) {
            for (GridServiceContainer gsc : gsa.getGridServiceContainers()) {
                // ....
            }
        }
    }
    public void findStartedGridServiceManagers() {
        Admin admin = new AdminFactory().createAdmin();

        // wait at least for one agent
        admin.getGridServiceAgents().waitForAtLeastOne();

        for (GridServiceAgent gsa : admin.getGridServiceAgents()) {
            for (GridServiceManager gsm : gsa.getGridServiceManagers()) {
                // ....
            }
        }
    }
    public void findStartedLookupServices() {
        Admin admin = new AdminFactory().createAdmin();

        // wait at least for one agent
        admin.getGridServiceAgents().waitForAtLeastOne();

        for (GridServiceAgent gsa : admin.getGridServiceAgents()) {
            for (LookupService ls : gsa.getLookupServices()) {
                // ....
            }
        }
    }

A fully running example of a Scaling Agent is available in the Solutions & Patterns section.

Admin Construction

The Admin API uses the AdminFactory in order to create Admin instances. After you finish working with the Admin, its Admin#close() method should be called.

The Admin API discovers all the advertised services from the Lookup Service. Use the AdminFactory#addGroup to define which lookup groups. The lookup locators can also be used for non-multicast enabled environments using AdminFactory#addLocator. If the services started are secured, the username and password can be set on the Admin API as well.

Discovery Process

When the Admin is created, it starts to receive discovery events from all the advertised services/components within its lookup groups and lookup locators. The events occur asynchronously and the data model within the Admin API gets initialized in the background with services coming and going.

This means that just creating the Admin and calling a specific "getter" for a data structure might not return what is currently deployed, and you should wait until the structures are filled. Some components have a waitFor method that allows waiting for a specific number of services to be up. When navigating the data model, the Admin API provides its most up-to-date state of the system it is monitoring.

Domain Model

The Admin Domain Model has representation to all the data grid-level main actors. They include:

admin_DomainModel.jpg

The Admin functionality is designed to interact with a service grid deployment. For StandaloneProcessingUnitContainer and IntegratedProcessingUnitContainer, components such as GridServiceAgent and GridServiceManager are not started by default, therefore portions of the Admin functionality aren't available.

Accessing the Domain Model

There are two ways to use the Admin API to access information:

  • Call specific "getters" for the data and iterate over them (as shown in the example at the top of the page).
  • Register for specific events using the Admin API. Events are handled by different components of the Admin API in similar manner. We will take one of them and use it as a reference example.

If we want to register, for example, for Grid Service Container additions, we can use the following code (removing the event listener is not shown here for clarity):

admin.getGridServiceContainers().getGridServiceContainerAdded().add(new GridServiceContainerAddedEventListener() {
    public void gridServiceContainerAdded(GridServiceContainer gridServiceContainer) {
        // do something here
    }
});

Removals are done in similar manner:

admin.getGridServiceContainers().getGridServiceContainerRemoved().add(new GridServiceContainerRemovedEventListener() {
    public void gridServiceContainerRemoved(GridServiceContainer gridServiceContainer) {
        // do something here
    }
});

Since both removals and additions are common events that we would like to register for at the same time, we can use:

admin.getGridServiceContainers().addLifecycleListener(new GridServiceContainerLifecycleEventListener() {
    public void gridServiceContainerAdded(GridServiceContainer gridServiceContainer) {
        // do something here
    }

    public void gridServiceContainerRemoved(GridServiceContainer gridServiceContainer) {
        // do something here
    }
});

All other data structures use similar APIs to register for events. Some might have specific events that go beyond additions and removals, but they still use the same model. For example, you can register for Space mode change events across all currently running Space topologies and Space instances:

admin.getSpaces().getSpaceModeChanged().add(new SpaceModeChangedEventListener() {
    public void spaceModeChanged(SpaceModeChangedEvent event) {
        System.out.println("Space [" + event.getSpaceInstance().getSpace().getName() + "] " +
        "Instance [" + event.getSpaceInstance().getInstanceId() + "/" +
                event.getSpaceInstance().getBackupId() + "] " +
        "changed mode from [" + event.getPreviousMode() + "] to [" + event.getNewMode() + "]");
    }
});

Of course, you can register the same listener on a specific Space topology, or event on a specific SpaceInstance.

Last, the Admin interface provides a one-stop method called addEventListener that accepts an AdminListener. Most event listeners implement this interface. You can create a class that implements several chosen listener interfaces, call the addEventListener method, and they will automatically be added to their respective components. For example, if our listener implements GridServiceContainerAddedEventListener and GridServiceManagerAddedEventListener, the listener will automatically be added to the GridServiceManagers and GridServiceContainers.

Security

If you are using the Admnistration API in a secured environment, there are several things that must be taken into consideration when accessing the service grid or deploying grid components (Spaces and Processing Units).

Constructing the Admin Instance

When using a secured Service GridClosed A built-in orchestration tool which contains a set of Grid Service Containers (GSCs) managed by a Grid Service Manager. The containers host various deployments of Processing Units and data grids. Each container can be run on a separate physical machine. This orchestration is available for XAP only., the Admin instance needs to be constructed with a principal which is granted sufficient privileges based on the operations being performed using the administration API. For example, grant Manage Grid to start a Grid Service Manager (GSM) and grant Provision PU to deploy a processing unit.

The following creates an Admin instance with the user "user/password".

Admin admin = new AdminFactory().addGroup("gigaspaces").credentials("user", "password").createAdmin();

For security other than username/password, refer to the Authentication topic in the Security section of the Administration guide.

Space Deployment

Deploying a secured Space:

...
admin.getGridServiceManagers().deploy(new SpaceDeployment("mySpace").secured(true));

Deploying a secured Space with credentials supplied. These credentials propagate to internal services, such as Space Filters.

...
admin.getGridServiceManagers().deploy(new SpaceDeployment("mySpace").userDetails("myUser", "myPassword"));

Processing Unit Deployment

Deploying a secured Processing Unit. This will deploy a Processing Unit with a secured embedded Space.

...
admin.getGridServiceManagers().deploy(new ProcessingUnitDeployment("myPu").secured(true));

Deploying a secured Processing Unit with credentials supplied. With this approach, credentials do not need to be hardcoded in the pu.xml declaration. These credential propagate to all the beans that require a proxy to the Space.

...
admin.getGridServiceManagers().deploy(new ProcessingUnitDeployment("myPu").userDetails("myUser", "myPassword"));