Contents
We are excited to present Monterey Middleware, a platform for designing and hosting highly scalable applications. The key feature of Monterey Middleware is application mobility, enabling an application to be moved in real-time while preserving all data and ordering of messages, which in turn provides:
Alongside our platform is our Eclipse-based development environment: our Eclipse update site can be used to install the Monterey Spring Edition into an existing Eclipse installation such as SpringSource's STS; alternatively the Monterey Studio stand-alone application can be installed. This development environment makes it easy to create applications for the platform.
Monterey Service development allows one to create scalable elastic applications while focusing on the core business logic, ignoring the underlying messaging and distributed execution details. Similarly, Monterey Classic presents a core messaging-based API that is simple and uncluttered, meaning it's easy to get started and straightforward to use. Unlike other platforms, our simple APIs mean there isn't any vendor lock in, but still powerful enough to provide a plethora of advanced features, with more being developed.
The patented underlying technology supports many areas of functionality beyond what is presented here, but we need to know from our clients what new features are required and how they should be made available. If you're interested, some of the capabilities we are considering are suggested in the Appendix section.
We'd really like to hear your thoughts on what works well and what should be added or changed. Let us know especially if there's an application or area that you're working on which Monterey Middleware could host if only it had feature X.
To start, we will try to make clear the terms we are using:
Distributed mediation refers to the ability to have a large number of these processes spread over a network, instead of confined to a single machine. Monterey Middleware enables you to distribute these processes effectively and to change the distribution on-the-fly, allowing the careful and efficient use of available resources.
Monterey Middleware does this by providing a framework for application mobility. Given an application that knows how to serialize its state, Monterey Middleware allows for migrations across a network while preserving the ordering of messages, without interruption to clients.
To aid in the development and testing of Monterey applications, we provide the Monterey Development Environment. This is built on the Eclipse IDE, and includes tutorials, documentation, and wizards. It is the simplest way to get started with Monterey Middleware, whether writing your own new application or adapting an existing codebase.
The Monterey development environment can be installed in an existing Eclipse installation via an Eclipse Update Site (e.g. into SpringSource's STS or a vanilla Eclipse).
Alternatively, it can be downloaded as a stand-alone application, known as Monterey Studio. This is a customized deployment of the Eclipse development environment, with additional features, tools and documentation for creating your own Monterey application.
There are three Monterey packs:
The Monterey Spring Edition can be installed in an existing Eclipse installation via an Eclipse Update Site (e.g. into SpringSource's STS 2.6.x or a vanilla Eclipse 3.6.x). You will need to install the Groovy-Eclipse plugin, by following the instructions at http://groovy.codehaus.org/Install+Groovy-Eclipse+Plugin
The Monterey update site is at:
The update site has these two packages:
To install Monterey via the update site, start by opening the Eclipse installation wizard under Help -> Install New Software. Click Add... and enter the name Monterey and the update site URL:
Ensure that both the Client and Service developer packs are selected, then click Next
Finally, select the CLOUDSOFT CORPORATION license and review the text. Select "I accept" followed by Finish. Tip It is possible to re-size the window to make it easier to review the content.
Once installation is complete, restart the IDE.
Monterey Studio can be downloaded from http://developers.cloudsoftcorp.com. Installation is simple: just unpack onto a machine with Java installed, it is ready to use. In the base directory, simply run the MontereyStudio executable.
When installed via the update site into an existing Eclipse installation, Eclipse will first prompt for a restart. After that, you are ready to go!
When using the stand-alone Monterey Studio for the first time, you must configure a workspace path. The workspace is the directory where you want to keep all of your project files. This directory will be created for you if it doesn't already exist. Remember to select the 'use this as the default workspace' option, or this question will be asked every time you run Monterey Studio. On first launch the default view is the welcome screen - this provides a few helpful links to get started, including displaying this documentation in an Eclipse pane, a link to start the tutorials, or getting rid of the welcome screen to begin with a blank workspace. The welcome page can re-opened at any point by clicking Help -> Welcome, while this user-guide and other help, tutorials and documentation can be accessed stand-alone by Help -> Help Contents or inside an Eclipse pane with Help -> Dynamic Help.
If you have installed Monterey into an existing Eclipse or SpringSource Tool Suite, the welcome screen is not available, but you can access the Monterey help via the Help -. Help Contents or Help -> Dynamic Help menu options as normal.
The simplest way to get started is to use the new project wizard, which can be found by navigating to File -> New -> Monterey Service Project. Write the service interface and service class implementation with your desired business logic, then you are ready to run...
For further details on the API used throughout the templates, see Developing Monterey Applications.
To write a Monterey classic application using the messaging-based API, use the wizard at File -> New -> Monterey Classic Project. The stubs template provides a simple skeleton project for writing the client-gateway and segment-service code.
Other templates are based around some of the tutorial projects, generating fully-formed projects which can be used as examples or as a starting point for creating your own applications.
For further details on the API used throughout the templates, see the section on Developing Monterey Applications.
To run a Monterey Application, you must first create a Monterey Application launch configuration. This may be done in the Run Configurations window, which can be accessed by clicking Run -> Run Configurations....
Separate run configuration types are provided for simulating a Monterey network on the local machine versus deploying the application onto a live network. You can create a new configuration by double-clicking Monterey Simulation or Monterey Deployment on the left-hand pane or, to re-use another projects configuration as a start point for a new configuration, right-click another configuration and select Duplicate. You may wish to rename run configurations if you're managing more than one project and have many of them.
The primary field for a run configuration is the Monterey Application (found on the first tab of the run configuration dialog that should be displayed initially), which specfies the application deployment descriptor file to be used. This defines such things as which OSGi bundles are required, which Java classes comprise the Monterey gateway and service components, what segments should initiallly be created, and so on.
For Monterey Deployment configurations, it is also necessary to specify how to connect to the running network's control plane. In many situations this requires choosing Remote Monterey Server over Web API from the drop-down list, and providing the necessary URL and user credentials provided by the network administrator.
The run configuration can be run straight from this window. There is also the Run menu, which offers a choice from a selection of recently used configurations under Run History or to go to the Run Configurations window to select and run a configuration from there.
Once the application is running, the easiest way to set-up the network is using the Quick Setup option found on the drop-down menu for the Resources view. These options allow the rapid provision, roll-out and configuration of a network of many machines to quickly start testing an application or act as a starting point for a custom network.
Further details on the management console, manual deployment (i.e. without the management console) and other run-time considerations can be found in the section on Running Monterey Applications.
The next stage is the Monterey Tutorial, where you take the skeleton classes mentioned above, and add features and code to complete the project. The tutorial can be accessed from the Monterey Studio Welcome page, found at the top of the Help Menu.
You may find it easier to experiment with the completed example instead. There is also a fully featured stock trading example available to run with. Create a new Monterey application run configuration, and select the 'ezbrokerage' project. This is a stock exchange complete with traders. Take a look at the bot view, described in more detail later in this manual, to try configuring the behaviour.
Once you are comfortable with the outline of a Monterey Application, you may want to experiment with the framework. Either changing the chatroom example, or working from the stubs are both good ways to get started. The chatroom example is very simple and there is plenty of room for expansion to add new commands and behaviour. Alternatively why not try using Monterey Middleware to write a simple online game?
There is a forum/mailing list available and we'd love to hear your ideas and suggestions, to find out what you've done, and to help you get the most from Monterey Middleware.
Monterey Middleware requires JavaSE 1.6.
Note: applications written against some earlier versions of Monterey Middleware may require code or structural changes in order to run under this major release update. Please consult docs/release-notes.txt for more details.
You can develop Monterey applications in two ways - using either the Monterey Studio standalone IDE, or by adding the Monterey features to an existing Eclipse or SpringSource Tool Suite installation.
Monterey Studio can be used as both a standalone product and as Eclipse plug-in features for an existing Eclipse installation. The standalone product is recommended. These installation instructions are for the standalone product.
Your product distribution should include a ZIP archive for your platform named similar to the following:
Monterey-[version]-[platform].zip
Unpack this archive to a suitable install location on your system.
Note
Do not use the jar utility distributed with the Java SDK to extract the archive as it does not consistently preserve executable file permissions on Mac and Linux platforms.
The contents of the install package are as follows:
To get started, locate and run the MontereyStudio executable in the MontereyStudio folder. The first time you launch Monterey Studio, you will be prompted for a location where your workspace data will be stored. We recommend you accept the default workspace location, which should be a directory named monterey-workspace in your home directory.
Monterey can be installed using Eclipse's "Install New Software" functions. This also applies to Eclipse derivatives such as SpringSource Tool Suite. Eclipse 3.6.1 and SpringSource Tool Suite 2.6.0 are supported by Cloudsoft[*].
| [*] | Correct at the time of writing. We will be supporting newer versions of these applications as they become available. |
Before installing Monterey, you will need to install the Groovy-Eclipse plugin, by following the instructions at http://groovy.codehaus.org/Install+Groovy-Eclipse+Plugin
Select the Help -> Install New Software... menu option. Press the Add button in the top-right of the Available Software dialog box, and enter the following information into the Add Repository dialog:
The Monterey update site is at:
Click OK. Eclipse will now display the software packages available from this location:
Having chosen the features to install, click Next and follow the instructions on-screen. Eclipse will prompt you to restart; once this is done, Monterey is installed, and its feature will be available to use in Eclipse.
Segments define the boundaries of independent data processing performed in a Monterey application. They are also the unit of mobility (see migration). Segments are independent; they cannot depend on the state contained in others. A major design decision for writing Monterey applications is how to decompose the application into independent segments.
Each segment has a unique name to identify it, and every message sent through the Monterey network for mediation includes the identity of the relevant segment. Within the management console, segments have further information attached, including a name and a colour to distinguish it in the graphs and charts. Information about using these fields for display is available in the section on Running Monterey Applications.
The Monterey application executes on the Monterey platform, which has four standard node types: Local Point of Presence (LPP) nodes act as client gateways, presenting the application to end-users; Mediator (M) nodes host processing for a collection of application segments; Mediation Router (MR) nodes route requests from the LPPs to the appropriate M nodes based on the request's segment; and Transmission Proxy (TP) nodes route responses and updates from application segments on M nodes to relevant users connected at the various LPP nodes.
When writing a Monterey application, developers need only think about the code for processing requests at a segment and about the client code for making these requests. The Monterey platform transparently handles the routing of these requests (i.e. routing of the messages) and handles the dynamic changes to the network and infrastructure.
Monterey allows a service developer to focus on their core business logic, by writing an interface that is exposed to clients of the service. The underlying messaging APIs are entirely hidden from the service and client developers.
In Spring terminology, each segment is a bean that encodes the application's business logic. Each bean exposes an interface through which it can be accessed by client-code. Importantly, these beans are mobile: individual beans can be suspended, migrated to a different node, and resumed without impacting the rest of the application. In this distributed application, calls from the client are automatially serialized and routed to the appropriate bean where they are processed, and the response sent back to the client (a useful analogy for this is RMI remoting). All the client and service developers need do is ensure that the parameters and return types of their methods are serializable.
This approach is best illustrated with an example. Consider a Hotel Booking Availability service for Foo Hotels, a world-wide hotel chain. The service can be logically partitioned with each hotel being a segment. Each segment is stateful, and is the definitive source of hotel availability information. Each segment exposes an interface for booking a room and cancelling bookings in that particular hotel. The business logic for each hotel is responsible for tracking the room bookings, and accepting/rejecting booking requests. A client consuming this service first looks up the particular hotel and then makes calls on the hotel interface to make its desired bookings.
To create a Monterey service, the best starting point is the Monterey Service Project wizard. This will normally create a pair of projects, one containing the interface, and the other containing the implementation. This separation allows the light-weight interface project to be bundled and given to the client-side development team (who do not need access to the implementation.) You can however override this behaviour and place all the classes into the same project.
The Monterey Service Project is available under the File -> New menu in the Java perspective. Alternatively select the File -> New -> Project... menu option to see a list of all project types; expand the Monterey Middleware group, select Monterey Service Project, and then click Next. You will then see the Create a Monterey Service Project dialog:
The wizard asks for the service interface and implementation to be used for each segment. The wizard then creates the required classes and meta-data files to allow this application to be deployed to a Monterey network.
You have the following options on this dialog:
Project name: the name of the new project. If the option is selected to "create api and implementation in separate projects" then two projects will be created with this project name prefix, with suffixes ".api" and ".impl".
Java package root: the package name of the new classes and interfaces. This is normally the same as the project name but can be changed if needed. the public interfaces and classes are created in this package, while the service implementation classes are generated in a sub-package with suffix ".impl".
Monterey classes prefix: an optional prefix to be applied to the names of the supporting classes (it does not apply to the service interface nor the service class names.)
Service interface: the name of a Java interface, which will be the externally-facing API of the Monterey network service. If "create service interface" is selected then this name must be unqualified and the interface is generated in the "java package root"; otherwise the interface name should be fully qualified.
Service class: the name of a class that will implement the interface, and thus contain the segment's business logic. This class's code will be executed inside the Monterey network. If "create service class" is selected then this name must be unqualified and the class is generated in the ".impl" sub package; otherwise the class name should be fully qualified.
Create service interface (uncheck to use pre-existing): check this box to create an empty interface with the above name; uncheck if you do not require this interface to be created (if, for example, you have a pre-written interface.)
Create service class (uncheck to use pre-existing): check this box to create an empty implementation class with the above name; uncheck if you do not require this class to be created (if, for example, you have a pre-written interface.)
Create api and implementation in separate projects (with suffixes .api and .impl): check this box to create two projects - one project with the suffix .api containing the interface, and one with the suffix .impl containing the implementation class. Unchecked, a single project is created and all types are placed in this project.
Support external proxy LPP connections: check this box to create an LPP-client-gateway that supports proxy LPP connections. This is necessary for external clients that are behind a firewall or that have a private IP. They require a proxy connection via an LPP in the monterey network. See the section Client-side firewalls and private IPs.
LPP-client-gateway that registers the bot. See the section Testing and Bots.
Initial segments: this is the list of initial segments that is placed in the application descriptor configuration file, and will be started when the service is deployed into a Monterey network. For more information on segments, refer to Essentials of a Monterey Application.
When you click Finish, the project(s) and types will be created.
The next step for the developer is to flesh out the service interface and implementation with their business logic. Care should be taken to ensure that all parameters and return values are serializable.
That's it. The service developer can now deploy and manage the Monterey application. The auto-generated deployment descriptor in the conf directory is used when deploying the application.
To allow client-side developers to use the new Monterey service, the API code needs to be made available. Simply generate a jar for the .api project and make this available to client-side developers.
You will need to supply the API to client-side developers for them to be able to take advantage of your service on a Monterey network. Simply generate an OSGi bundle (i.e. a Jar) for the api project. The standard way to do this in Eclipse involves:
The client-side developers can then take the exported JAR bundle, and import it into their project. It can then be used as described in Client-side developers.
You may find it convenient during development to provide a bundle of the impl project also. This bundle will contain the LocalServiceLocatorImpl class - an implementation of the service locator that keeps the services in-process. This will allow the client-side developers to test against the service without requiring a Monterey network or simulator.
A client-side developer can connect to a Monterey network and call the Monterey Service. The client uses a service locator to lookup the desired segment; the returned object exposes the service interface, and transparently routes the method calls over the Monterey network to call the implementation class.
You can start your Monterey client project for any kind of Eclipse Java project. You only need to add the Monterey nature to this project. To do this, right-click on the project in the Eclipse Project Explorer view, and select Configure -> Convert to Monterey Project.
The client-side code needs two jars: first, a Monterey jar, and second, the Monterey service APIs. It is the responsibility of the service developer to publish the service API Jar. The Monterey jar can be obtained by right-clicking on the project and selecting Monterey Middleware -> Add Monterey Jar (if this option is missing, see above to find out how to make your project a Monterey project.) This will copy the monterey-embedded-node.jar file into the root of your project. You should ensure this is added to your build path, moving it if necessary.
Connecting to a Monterey service involves instantiating a MontereyNetworkEndpoint and a ServiceLocatorImpl. The MontereyNeworkEndpoint supports authentication and message-passing; the ServiceLocatorImpl allows one to lookup a desired segment to get a proxy for the remote service instance. The client-code looks up the desired segment, and invokes methods on that segment. Method calls are synchronous: they block until the server-side has executed the method and returned the result, or until any exception thrown by the service is returned to the client.
The credentials used to connect to the Monterey network must match a user in either the client or admin role (as configured in the web-users.conf).
Below is some example Java code for a client using a hotel booking availability service:
import com.cloudsoftcorp.monterey.servicebean.access.api.MontereyNetworkEndpointImpl;
import com.cloudsoftcorp.sample.booking.BookingAvailabilityServiceLocatorImpl;
import com.cloudsoftcorp.sample.booking.BookingAvailabilityServiceLocator;
import com.cloudsoftcorp.sample.booking.BookingAvailabilityService;
public static void main(String[] args) {
...
MontereyNetworkEndpointImpl endpoint = new MontereyNetworkEndpointImpl();
endpoint.setManagementNodeUrl("http://thehostname:8080");
endpoint.setUsername("guest");
endpoint.setPassword("password");
endpoint.setLocation("GB-LND");
endpoint.start();
BookingAvailabilityServiceLocator serviceLocator = new BookingAvailabilityServiceLocatorImpl(endpoint);
serviceLocator.getHotel("The Ritz").createProvisionalBooking(checkInDate, checkOutDate);
...
endpoint.shutdown();
}
An example of the Spring configuration for instantiating the service locator is shown below:
<bean name="montereyEndpoint" class="com.cloudsoftcorp.monterey.servicebean.access.api.MontereyNetworkEndpointImpl" init-method="start" destroy-method="shutdown">
<property name="managementNodeUrl" value="http://thehostname:8080"/>
<property name="username" value="guest"/>
<property name="password" value="password"/>
<property name="location" value="GB-LND"/>
</bean>
<bean name="bookingAvailabilityLocator" class="com.cloudsoftcorp.sample.booking.BookingAvailabilityServiceLocatorImpl">
<constructor-arg ref="montereyEndpoint"/>
</bean>
Note that calls to serviceLocator.getService(String) are cheap - they do not involve any remote communication.
Services are designed to be mobile - that is, they can be moved around the Monterey network, relocated to different nodes in the network. This may happen by a manual operation by a network administrator, or in response to decisions made by policies (for example, provisioning extra nodes and moving processing onto new nodes in response to increased demand.)
The service developer gets mobility for free if their class is serializable. When migrating a segment, the default behaviour is to serialize the implementation instance, send it across the wire to the new node, and deserialize it.
In many cases, standard serialization is sufficient. However, in some cases it is necessary to know when migration is occurring - you can listen for lifecycle events that happen before and after a service is moved. For example, one may have to open/close connections to external resources or start/stop additional threads.
To receive these lifecycle events, your service implementation class can use the @PreSuspend and @PostResume annotations provided by com.cloudsoftcorp.monterey.servicebean.annotation. These annotations can be applied to void methods with no arguments. The @PreSuspend annotated method is called by Monterey immediately before the service instance is serialized. The @PostResume annotated method is called by Monterey after the service instance is deserialized at its new location, and before Monterey resumes calling the service's methods.
If multiple methods are annotated with @PreSuspend or @PostResume, they will all be called but the order is not guaranteed. If a method is annotated that requires parameters then it will not be called.
Alternatively, your service implementation class can implement the interface SuspendableBean. This interface provides two methods:
The suspend method is equivalent to using the @PreSuspend annotation; the resume method is equivalent to using the @PostResume annotation.
If annotations and the SuspendableBean interface are used simultaneously, then the annotated methods will be called first and then the interface's suspend or resume methods. The suspend() and resume() methods are guaranteed to be called exactly once, even if they are also annotated.
The typical lifecycle of a segment bean is: * On segment initialization at node X:
- instantiate the bean.
The auto-generated SegmentService class extends AbstractBeanSegmentService, which provides the default behaviour described above. The SegmentService class can be changed to customize this behaviour. The three most important methods for overriding in SegmentService are:
A powerful use-case is to use an existing class without modification. This is demonstrated in the code snippets below for a pre-existing class FooImpl:
@Override
protected Foo newBean(String segment) {
return new FooImpl();
}
@Override
protected Serializable suspendBean(Foo bean) {
return bean.getMemento();
}
@Override
protected BookingService resumeBean(Object suspendedState) {
return new FooImpl((FooMemento)suspendedState);
}
The files generated by the wizard are listed below. In common use-cases, most of these files can be safely ignored by the developer:
When a client-side developer connects to a Monterey network using the MontereyNetworkEndpoint, by default a server socket will be opened at the client-side. This allows nodes in the Monterey network to open socket connections to the client-side endpoint for efficient direct communication. However, if the client-side endpoint is on a machine with only a private IP or is behind a firewall, this approach is not possible.
The client-side developer can configure the endpoint so that it opens a single socket connection to an LPP in the monterey network. This is done by setting the additional property hasPrivateIp:
MontereyNetworkEndpointImpl endpoint = new MontereyNetworkEndpointImpl(); endpoint.setHasPrivateIp(true);
On the server-side, one or more LPP must be configured to accept these connections.
There needs to be a suitable LppClientGateway class deployed with the monterey service, and LPP(s) need to be rolled out. This can be done automatically in the Monterey Service Project wizard by checking the box Support external proxy LPP connections.
This auto-generates several artifacts in the project. First, there is an LppClientGateway which includes the following code:
public class MyExampleGateway extends BeanLppClientGateway {
public static class Factory implements LppClientGatewayFactory {
public LppClientGateway newClientGateway() {
return new MyExampleGateway();
}
public LppStateBackup newClientGatewayBackup() {
return null; // Unsupported
}
}
public MyExampleGateway() {
setSupportsProxyingLpp(true);
}
}
There is an OSGi declarative service file auto-generated in the project's META-INF/OSGI-INF directory. Lastly, the deployment descriptor configuration file identifies that this LPP implementation should be used.
This area is one of the main focuses for future versions of Monterey. We want to make it as easy to use and powerful as possible, and make the integration with Spring smoother. There are a number of features under consideration; the opinions of the community would be most welcome:
Developers can write Monterey Applications using the classic message-based APIs. Writing an application comprises the following activities:
The New Monterey Classic Project Wizard, described below, can automate much of the above work, but they are described here for completeness. The Monterey network also introduces additional nodes, between the LPP and Mediator nodes, in order to take care of routing messages between the services (2) and gateways (3), preserving consistency while segment migration and network topology changes are being made. These nodes are described elsewhere; although crucial to the operation of the Monterey network, they are mostly invisible to the application developer.
Each segment is allocated a single associated MediationSegmentService instance, residing on a given Mediator node in the Monterey network. A single Mediator will host many such services, each configured to process mediation requests for a different segment. Obviously a MediationSegmentService will only see messages for the segment is it processing.
A MediationSegmentService is a process that lives on the network, that can receive messages from clients, process them, and if necessary reply to specific or all clients about the given segment on the network.
The MediationSegmentService interface (in com.cloudsoftcorp.monterey.network.api) looks like:
public interface MediationSegmentService {
void doMediation(SenderReference sender, Object data);
void initialize(SegmentServiceContext context, Object stateToResume);
Serializable shutdown();
}
We can clearly see the responsibilities of a MediationSegmentService. The most important method is doMediation. This method is called when the Mediator receives a message in the corresponding segment.
When the segment service is initialized it is passed the existing state (if any) and a SegmentServiceContext object to allow it to communicate; and it provides the following methods:
public interface SegmentServiceContext {
public void send(SenderReference ref, Serializable data);
public void broadcast(Serializable data);
public void error(String message, Throwable optionalException);
public String getSegment();
}
The context instance is passed to the service's initialize method, which also provides a convenient hook for the service class to conduct any bootstrapping activities.
The Monterey Middleware framework guarantees that no messages will be delivered to the service (doMediation will not be called) until after the initialize method has completed.
The initialize method is one of the lifecycle methods that together permit the transfer of state between pre- and post-migration instances of the segment service:
Note that the initalize method method takes an Object, but shutdown must return an instance of Serializable. This asymmetry is intentional, and reflects the minimum requirements for each method.
At the client facing end of the network are the LPP nodes, providing a gateway onto the Monterey network itself. In the chat example from the tutorial, the gateway provided a web interface to end users so they could chat.
More technically, these nodes run code that conforms to the LppClientGateway interface (in com.cloudsoftcorp.monterey.network.api):
public interface LppClientGateway {
void onPrivateMessage(String userRef, String segment, Object data);
void onPublicMessage(String segment, Object data);
void initialize(ClientGatewayContext context, Object stateToResume);
Serializable shutdown();
}
The methods are fairly self explanatory. initalize is called on creation, shutdown on termination, onPublicMessage and onPrivateMessage are called when a message arrives at the LPP node, dependant on the type of message (i.e. public messages are the broadcasts).
As above in the mediator case, the LppClientGateway is provided with a context object to allow it to send messages on the network, specifically something that complies with the ClientGatewayContext interface (in com.cloudsoftcorp.monterey.network.api):
public interface ClientGatewayContext {
public void sendMediationRequest(String userRef, String segment, Serializable data);
public void error(String message, Throwable optionalException);
public void sendToMonitor(Object data);
}
The sendMediationRequest method is used to communicate with the Monterey Network, and error is used to raise errors, forwarded onto the management console. sendToMonitor is used for out-of-band control messages, sent straight to the control plane, and this is used internally to announce bots for example.
If the gateway class implements the optional ManagementExtension interface, can optionally be implemented to indicate that gateway is capable of processing management messages, such as bot configuration commands:
public interface ManagementExtension {
void onManagementMessage(Object data);
}
There is an example of handling ManagementExtentions in the bot section of the tutorial. There are two existing types of management messages - bot configuration messages, and the current (simulated) time-of-day as set in the Geographies View.
Finally, the gateway class can be run at one of two locations, either at a Vanilla or a Satellite LPP. The Satellite LPP is so client specific code can be run outside of the normal Monterey network. Client code (LppCLientGateway implementations) are unaware of precisely where they are running.
Note
The use of satellite LPPs for hosting bots is currently under review, and is subject to change in the next Monterey release. For the time being, however, satellite deployment of gateways can be specified in the Monterey application deployment descriptor file by adding satellites true inside the bots{} section.
Within the management console there is a round trip time (RTT) view. This shows the total time taken for a message to be sent by an LPP, routed to the correct mediator, processed, and a response to be routed back to the LPP. The graphs show the maximum and the average over the last few seconds.
In order to do RTT calculations, the application developer must flag certain mediation requests as expecting an immediate response. If the class of the message being sent in a mediation request is annotated with @MediationRequestWithImmediateResponse, then the type taken for the response to arrive will be measured (this annotation class is in the package com.cloudsoftcorp.monterey.network.api).
For example, when using the built in EZ-Brokerage example, you can see a line graph showing the RTT values for the network; if you try looking at it using the chat example within the tutorial, the graph is empty because no chatroom message typess are marked as requiring an immediate response.
The New Monterey Classic Project wizard is capable of generating a "minimal" implementation of an entire Monterey application, including:
The wizard is often the most convenient starting point when developing a new Monterey application. It can be accessed by selecting New -> Project... -> Monterey Classic Project in the File menu or right-click menu in the Project View.
The most common use-case is to generate a project from the "Stubs" template. This creates the required project and directory structure, and creates empty (commented) implementations of the essential MediationSegmentService and LppClientGateway interfaces (described above). It also generates the OSGi meta-data MANIFEST.MF and OSGI-INF, and a conf directory containing a basic application deployment descriptor configuration file.
Other files that can be optionally generated include a very simple web-server and an empty bot implementation.
The comma-separated list of initial segments can be specified in the wizard. This can later be edited in the application deployment descriptor file.
An alternative code templates for generated a project is "Nothing". This creates the required Eclipse project and directory structure, but does not genreate any code or OSGi meta-data files.
Note
Additional (optional) templates may be included that generate complete working Monterey applications for tutorial and demonstration purposes.
The following resilience modes are available:
NONE - Fast Restart at Mediator SegmentService implementations
A simple strategy for when execution speed is critical, or when node failure is not expected.
CHECKPOINT - Fast Recovery at Mediator SegmentService implementations
The application developer inserts explicit checkpoints to limit the amount of data that can be lost on node failure. This strategy is appropriate for when the application can handle some message/transactional inconsistency (e.g. telling users to resend or disregard immediately prior transactions).
LOSSLESS - Full Redundancy Built-in to Monterey Middleware
Guaranteed message delivery and processing, even in the event of node failures. Currently, this is only available in classic mode and not with the service development interface-based approach.
In some situations other strategies may be more appropriate and can be developed by arrangement with Cloudsoft. In particular where persistent/reliable messaging is used for point-to-point communications or an underlying virtualization layer offers disaster recovery capabilities, the redundancy offered by these components can reduce or eliminate the demands on resilience at the Monterey level. However in many situations Monterey is the most efficient level at which to maintain the redundancy, and significant performance and efficiency gains can be achieved by bypassing resilience in underlying components.
When using NONE, any replication required is the responsibility of the application developer. On node failure, in-flight messages may be lost; on mediator failure, segment state may be lost - a new mediator will be allocated to restart the segment service with empty initial state.
When using CHECKPOINT, the segment-service code can call:
segmentServiceContext.getResilienceSupport().checkpoint(mydata); segmentServiceContext.getResilienceSupport().delta(mydelta);
The first call will send a copy of mydata to each of the replicants, which is assumed to be a snapshot of the complete state - this will be used when initialising a replacement segment service if the master node fails. The second call will send mydelta, which should be a delta describing all changes since the previous checkpoint or delta. The replicant can then piece together these deltas to produce a copy of the complete state.
When using LOSSLESS, all mediation requests and responses are automatically backed up at the replicants. In the event of nodes failing, these requests/responses will be resent. Every mediation request processed by the segment master will be given to each replicant in the same order. The replicant should be implemented in a deterministic way so that the master and backup have the same state given the same sequence of mediation requests. The application developer does not have to call checkpoint or delta because the mediation requests themselves are automatically replicated.
If a mediator fails while processing a mediation request message, the message will be re-processed when a backup mediator is promoted. It is guaranteed that this will be the next message for the given segment, and the messages is flagged as a potential duplicate. A segment service can ask whether the current message is a potential duplicate by calling:
segmentServiceContext.getResilienceSupport().isCurrentPotentialDuplicate()
See also the section on Run-Time Resilience Configuration.
To use checkpointing in the Monterey Service Development mode (as oposed to the classic mode), the developer needs to inject the SegmentServiceContext into the service class implementation. Some sample code for this is shown below.
Add the following code to the service class:
private transient SegmentServiceContext context;
public void setSegmentServiceContext(SegmentServiceContext context) {
this.context = context;
}
Then in the service class, call context.checkpoint(this) wherever required. If using deltas, a SegmentStateBackup class is also required (see next section), whose getState() method must return an instance of the service class.
In the implementation package, you'll find an auto-generated SegmentService class, which is responsible for instantiating, suspending and resuming the segment instance. This can be modified to call the setter method when the instance is instantiated and when it has been deserialized. For example:
protected com.example.MyServ newBean(String segment) {
MyServImpl result = new MyServImpl();
result.setSegmentServiceContext(getContext());
return result;
}
@Override
protected void notifyOfResume(com.example.MyServ val) {
((MyServImpl)val).setSegmentServiceContext(getContext());
super.notifyOfResume(val);
}
For the lossless resilience mode or when using checkpointing with deltas, the application developer must implement the SegmentStateBackup and LppStateBackup interfaces. Their purpose is to maintain a copy of the current state of a segment or LPP. For checkpointing using just the checkpoint() method, the latest checkpointed state is stored automatically without having to implement these interfaces.
The backup classes to use for the application are defined (and instantiated) by the MediationSegmentServiceFactory.newSegmentBackup and the LppClientGatewayFactory.newClientGatewayBackup methods. The factories are auto-generated when using the New Monterey Classic Project Wizard's "stubs" template, and the factory is registered as an OSGi service in the OSGI-INF meta-data. However, the methods newSegmentBackup and newClientGatewayBackup must be implemented by the user.
The default implementation is:
return null; // Unsupported
This needs to be changed to something like:
return new NameOfMySegmentStateBackup();
The lifecycle for a SegmentStateBackup or a LppStateBackup instance is that initialize() will first be called, supplying the current state. When that backup instance is no longer required, shutdown() will be called.
When the master segment-sevice calls checkpoint(mystate) or delta(mydelta), the SegmentStateBackup will receive calls to onCheckpoint(mystate) and onDelta(mydelta) respectively. For the LOSSLESS resilience mode, the SegmentStateBackup will receive calls to onMediation for every mediation request processed by the master.
For a simple segment service that uses either no resilience or only simple calls to checkpoint, the application can be used without providing a SegmentStateBackup implementation. However, for deltas to work the developer must implement SegmentStateBackup.onDelta to merge the deltas into a complete copy of the master's state. The method SegmentStateBackup.onCheckpoint should also be implemented.
The same applies to an LPP client gateway: for no resilience of for simple checkpointing, no LppStateBackup class is required; for deltas, LppStateBackup.onDelta should be implemented.
For lossless resilience, a SegmentStateBackup is required that implements onMediation. A common pattern is to rely solely on onMediation and to ignore delta() and checkpoint at the SegmentStateBackup.
However, for the LppStateBackup, the delta and checkpoint methods are all that is available. This is because LPPs often change state due to external events that the Monterey framework is not informed of (e.g. the LPP could have a HTTP server, which a new user connects to).
Segments can be added and queried at runtime. The ClientGatewayContext and SegmentServiceContext each provide access to a SegmentSupport instance:
public interface SegmentSupport {
Map<String, SegmentSummary> getSegments();
void addSegment(String segment, Callback callback);
}
The getSegments() method allows the code executing at the LPP and Mediator to retrieve the names and descriptions of all segments. The addSegment method allows a new segment to be created at runtime, where the callback is notified on successful creation of the segment.
Example use-cases of dynamic segments include a chatroom application that allows new topics of conversation to be started, or an on-line gaming application where each game is represented by its own segment.
The Monterey platform does not prescribe how client applications should connect to the gateways, however two straightforward methods are suggested:
Bots can be used by a developer to easily simulate multiple users generating load in the system. The bots' workrates are controlled throught the Bots View in the Management Console. This drives the bot code, which can be run on LPPs in the network. Example uses of bots include:
Of course, another approach to testing and generating load is to use an external tool (e.g. JMeter) to simulate external clients. The developer is free to choose which is easiest and most appropriate for their use-case.
When writing a Monterey Service, the Monterey Service Project wizard includes a checkbox for "Create and register a bot". This generates an empty bot class, and also an LPP client gateway that registers the bot.
The bot class implements ServiceBeanBot. The method doRequest(segment) is called periodically, based on the workrate that is set in the Bots View. An example bot class is shown below, which is for a service called "MyExample" (with class-prefix "MyExample" and a service interface called "MyExampleService"):
public class MyExampleBot implements ServiceBeanBot {
private MyExampleServiceLocator locator;
public void init(MontereyNetworkEndpoint endpoint) {
locator = new MyExampleServiceLocator(endpoint);
locator.setServiceCallsTimeoutInMillis(30*1000);
}
public void shutdown() {
// no-op
}
public void doRequest(String segment) {
MyExampleService service = locator.getService(segment);
service.myAction();
}
}
Most of this is auto-generated code. The important line added by the developer is service.myAction(), which is the method to be called on the service on each request. The logic for deciding which method(s) to call can be arbitrarily complex to fit the developer's use-case.
The auto-generated LPP class instantiates and registers this bot. For most simple use-cases, the developer will not have to touch the auto-generated gateway class. However, they are free to modify the class where necessary. In this example, the auto-generated classs MyExampleGateway would not need modified - the following line already does what we want:
addBot(new MyExampleBot());
For a Monterey classic application, a bot is defined by extending the class AbstractCdmUserBot, implementing a method which can generate messages within a given segment on demand. The Monterey framework, when bots are used, takes care of managing the activity rate based on GUI settings or script definitions. The framework periodically calls the method:
makeMediationRequest(BotSegmentBehaviour segment, AppCustomBotParametersT appCustomBotParameters)
The developer's implementation of this method should generate and send a mediation request via:
getContext().sendMediationRequest()
The developer must also wire up the bot in the LppClientGateway code, to instantiate it.
A simple example is shown below:
public class MyExampleBot extends AbstractCdmUserBot<MyExampleCustomBotParameters, MyExampleSegmentCustomBotParameters>{
@Override
public void makeMediationRequest(BotSegmentBehaviour<MyExampleSegmentCustomBotParameters> segment, MyExampleCustomBotParameters appCustomBotParameters) throws InterruptedException {
context.sendMediationRequest(botName, segment.getSegmentId(), "myexample");
}
public void onPrivateMessage(String userRef, String segment, String data) {
// TODO Any correlation logic for bot's workload goes here
}
public void onPublicMessage(String segment, String data) {
// TODO Any correlation logic for bot's workload goes here
}
}
public class MyExampleLpp implements LppClientGateway, LppClientGateway.ManagementExtension {
private final Collection<MyExampleBot> bots = new ArrayList<MyExampleBot>();
public void initialize(ClientGatewayContext context, Object stateToResume) {
// TODO other lpp logic goes here
MyExampleBot bot = new MyExampleBot();
bot.initializeBot("bot1", this, context);
bots.add(bot);
}
public Serializable shutdown() {
// TODO other lpp logic goes here
for (MyExampleBot bot : bots) {
bot.stopTrading();
}
return null;
}
public void onPrivateMessage(String userRef, String segment, Object data) {
// TODO other lpp logic goes here
for (MyExampleBot bot : bots) {
bot.onPrivateMessage(userRef, segment, (String)data);
}
}
public void onPublicMessage(String segment, Object data) {
// TODO other lpp logic goes here
for (MyExampleBot bot : bots) {
bot.onPublicMessage(segment, (String)data);
}
}
public void onManagementMessage(Object data) {
// TODO other lpp logic goes here
if (data instanceof BotBehaviour<?,?>) {
for (MyExampleBot bot : bots) {
bot.setBotParameters((BotBehaviour<?,?>) data);
}
} else if (data instanceof DemoClock) {
for (MyExampleBot bot : bots) {
bot.setClock((DemoClock) data);
}
}
}
}
public static class MyExampleCustomBotParameters {}
public static class MyExampleSegmentCustomBotParameters {}
The classes MyExampleCustomBotParameters and MyExampleSegmentCustomBotParameters are only used for advanced configuration of the bots' activity. In many use-cases, they can be safely ignored. However, when the advanced configuration is required, it is supplied via an implementation of the BotSetup interface:
public interface BotSetup {
void initialize(BotSet botSet);
Serializable getAppCustomBotParameter(String botId);
Serializable getAppCustomBotSegmentParameter(String botId, String segment);
}
The getAppCustomBotParameter method is called at the management node when the bot is registered. Its return type should match the parameter expected in the bot's makeMediationRequest method (e.g. in the example above MyExampleCustomBotParameters).
The getAppCustomBotSegmentParameter method is called for each segment. Its return type should match that expected by the bot's makeMediationRequest method (e.g. in the example above MyExampleSegmentCustomBotParameters).
To have the platform use the BotSetup class at runtime, it is necessary to create a simple factory class that implements the BotSetupFactory interface, and to register this with the OSGi services registry. The name of the registered instance can then be referenced in the Monterey application descriptor file thus:
bots {
setup "com.example.mybotsetupfactory.servicename"
}
If no custom BotSetup is required, then this line can safely be ommitted from the application descriptor.
The tutorial contains more examples of developing automated bots.
This section describes how to execute custom actions during the provisioning of network nodes. This enables users to perform setup before the monterey node is created. Possible examples include but are not limited to setting up a VPN or installing security certificates.
Creation of a network node involves 3 steps:
- Launching a Machine
- Calling custom provisioning actions
- Creating the Monterey Network Node
Supported actions include copying files from the management node to the network node and executing commands on the network node.
The API provided is defined by the following Java interfaces:
Please view the Javadoc for these interfaces for a complete description of the methods provided by the API.
The following example describes the steps involved in creating and deploying a simple listener that touches a file in the /tmp directory.
Create a new plugin project with a MANIFEST.MF file containing the following:
Bundle-SymbolicName: com.cloudsoftcorp.listener.example
Require-Bundle: com.cloudsoftcorp.monterey.location,
com.cloudsoftcorp.monterey.management
Create a new class in package com.cloudsoftcorpcom.listener.sample:
public class ExampleListener implements NodeProvisioningListener {
private static final Logger LOG = Logger.getLogger(ExampleListener.class.getName());
private final List<String> providers = Arrays.asList("aws-ec2","gogrid");
@Override
public void postCreateHost(Host host, MontereyLocation location) {
final String provider = location.getProvider();
if (!providers.contains(provider)) {
LOG.info("Skipping Listener: Host:"+host+"; provider:"+provider);
return;
}
try {
RemoteExecutionResult result = host.executeSsh(Arrays.asList("touch /tmp/example.txt"));
if( result.getExitValue() != 0 ) {
LOG.log(Level.WARNING, "Error touching file:"+result );
}
} catch (IOException e) {
LOG.log(Level.WARNING,"Could not touch tmp file",e);
return;
}
}
}
In the example above the listener actions are only performed if the provider is one of 'aws-ec2' or 'gogrid'.
Please refer to Creating Cloud Accounts section for details of the various providers that are available.
For private clouds where a custom locations conf file is supplied, the author specifies the provider name. The value in the configuration file will be available by calling MontereyLocation.getProvider()
The line that carries out the command is host.executeSsh(Arrays.asList("touch /tmp/example.txt")); The RemoteExecutionResult interface contains an exitValue property, which is inspected for success. See the Javadoc for RemoteExecutionResult for additional information on how this can be used.
Create an OSGi service definition for the listener using the File->New->Other->Component Definition menu item. The resulting component.xml file should look like this:
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"
name="com.cloudsoftcorpcom.listener.sample">
<implementation class="com.cloudsoftcorpcom.listener.sample.ExampleListener"/>
<service>
<provide interface="com.cloudsoftcorp.monterey.provisioning.api.NodeProvisioningListener"/>
</service>
</scr:component>
The name of the component must be globally unique.
The listener bundle needs to be activated on the management node. Update the application deployment descriptor file as shown:
bundles {
application {
...
}
management {
activate "com.cloudsoftcorp.listener.example"
}
}
When deploying the application via the Clouds View or Management Console, the com.cloudsoftcorp.listener.example bundle needs to be included.
When developing a Monterey application it is useful to test it in the simulator prior to deploying onto real clouds. On the simulator it is not possible to execute remote commands, and as such the host field in postCreateHost(Host host, MontereyLocation location) will be null. However, you will see log messages if your listener component and bundle have been correctly deployed, giving you confidence that the listener will trigger when deployed to other cloud environments.
Below is an example deployment descriptor file that demonstrates some of the configuration options and syntax:
MontereyApplication {
clientGateway "com.acme.chatroom.monterey.gatewayFactory"
segmentService "com.acme.chatroom.monterey.serviceFactory"
allowExternalLpps true
// Supported modes: NONE, CHECKPOINT, LOSSLESS
resilience ResilienceMode.CHECKPOINT, replicas:1
segments {
add "work"
add "travel"
}
bundles {
application {
activate "com.acme.chatroom"
}
management {
activate "com.acme.custompolicies"
}
}
}
The clientGateway is the factory to use at the LPP when creating a user's LppClientGateway instance. The value should match an OSGi service component name. The plumbing for this is generated automatically when using the New Project Wizard "stubs" template, in the file META-INF/OSGI-INF/gatewayFactory.xml. For a detailed description of how OSGi is used and configured, see the Appendix.
Similarly, the segmentService is the factory to use at the mediator when creating the instances of MediationSegmentService needed by an application. The value should match an OSGi service component name (e.g. in the auto-generated file META-INF/OSGI-INF/serviceFactory.xml.
The option allowExternalLpps indicates whether an LPP started externally can join an existing Monterey network (defaulting to false). When set to true, this allows for example embedding an LPP within another application. When true, the clientGateway can optionally be omitted; if omitted then LPPs must all be started externally and cannot be rolled out through the management console.
Resilience options are configured in the descriptor file. See the Developing for Resilience section for details. In brief, the mode is configured and (for CHECKPOINT or LOSSLESS) the number of replicas is also defined.
The segments section lists the initial segments that should exist when the application is first created. The simplest mechanism is to add a segment by defining only its id (which must be unique). However, there are other options that can be defined. For example:
add "NEW1", name:"A. Service", description:"example of a default service with a custom description and tags", tags:["sample"]
add "NEW2", name:"A. Restricted Service", description:"example of a default service with location constraints", location: 'startsWith("amazon.us")'
add "NEW3", name:"A.N. Other Service", description:"example of a service with a custom segmentService and keyword restraint", segmentService:"com.acme.OtherService", location: 'NOWHERE'
The segmentService overrides the default segmentService for this specific segment, hence different segments can use different MediationSegmentService types. It should be specified in the same format as segmentService. The keys name and description are used purely for presentation and can be any Java string. The tags key is metadata used to group segments; it is particularly useful in conjunction with custom policies or with the Bots View, simplifying configuration of a group of segments.
The location key can define a constraint which restricts the locations where the segment can operate, used during roll-out and by policies either to restrict it to a certain jurisdiction or forbidding it from entering certain jurisdictions. Note that if a constraint is changed at runtime such that the current location for a segment is invalid, the user will immediately be warned but the segment will not be moved automatically.
The format of the location field is Java code in a String (Groovy code, technically, so single quotes can be used inside the double quotes), operating on a location id String object implicitly and returning a boolean value. For example 'startsWith("amazon.us")' will permit amazon.us-east-1 and amazon.us-west-1, but not amazon.eu-west-1 or gogrid.us-east-1. Additionally the keywords ANYWHERE and NOWHERE are defined as true and false respectively, with ANYWHERE being the default.
The bundles section must define the OSGi bundles required when running the application. These are identified by the unique symbolic names as specified in the respective MANIFEST.MF files. The activate instruction can be placed directly in the bundles section to activate it both at the network nodes and at the management nodes. If a different set of bundles is required at the management nodes, this instruction can be placed in optional sub-sections application (started automatically on all LPP and mediator nodes created by the management plane) and management (started on management nodes, such as policies; however note that the management nodes may also need application bundles if custom classes are emitted during management, such as for workrates or bot behaviour).
Monterey adds a Clouds view to the Eclipse workbench, which helps with starting and managing Monterey networks. To show this view, select Window -> Show View -> Other.... Expand the Cloudsoft Monterey group and double-click on Clouds.
The Clouds view shows a set of cloud environments. These are configurations for (sets of) cloud providers, which allow users to deploy and run Monterey networks.
A cloud environment can include one or more cloud providers, and can include one or more locations per cloud provider. For each cloud provider, there is a cloud account that gives credentials and any other required configuration information. For example, a user could create a cloud environment that includes both GoGrid and AWS-EC2, and for AWS-EC2 could select a subset of the possible regions such as eu-west and us-east.
In the Clouds view, under each of the cloud environments is shown a list of Monterey networks running there. For each network the Clouds view shows the management URL, the application deployed (if any), and the network's status. You can manage the network using the Monterey Management Console: right-click on the network and select Launch management console or, alternatively, double-click the network.
By default, the Clouds view will contain a single cloud environment, Simulator.
New cloud environments can be added: right-click in the background of the Clouds view and select "New Cloud Environment...". Alternatively, select File -> New -> Other, then under Cloudsoft Monterey select Cloud Environment. This opens a wizard.
The first page of the wizard asks about the desired cloud providers and locations. Each top-level entry in the tree corresponds to an account with a particular cloud provider (or private cloud). The list of accounts can be edited by clicking "Manage Cloud Accounts...". In the tree, under each account there is a list of available locations. Some or all of these can be selected. This selection will control where Monterey networks can run.
The second page asks about the management plane's web-api credentials. The management console will subsequently use these credentials when connecting to a management node. For further descriptions, including those of the "client" and "admin" roles, see the documentation for "web-users.conf".
An existing cloud environment can be edited: right-click on it in the Clouds view and select edit. However, changes will not take effect in running networks.
A cloud account gives credentials and other configuration information for a given cloud provider or private cloud.
New cloud accounts can be added: right-click in the background of the Clouds view and select "Manage Cloud Account...". Alternatively, select File -> New -> Other, then under Cloudsoft Monterey select Cloud Account. This opens a wizard.
This wizard allows one to remove existing cloud accounts, edit them, or add new cloud accounts. To remove accounts, select one or more accounts from the list and click "Remove". To edit, select a single account from the list and click "Edit". To add a new account, click "Add".
The "Manage Cloud Account..." wizard also has a quick way of creating a cloud environment for a cloud account. Select one or more cloud accounts, and click "Create Cloud Environment...". This will open the New Cloud Environment wizard with all locations of the selected accounts pre-selected.
When adding a new account, the "New Monterey Cloud Account" wizard will appear. The first wizard page asks for the type of cloud account. Select the desired cloud provider and press Next.
The second page of the New Monterey Cloud Account wizard will prompt for a name - this name will appear in the "New Monterey Cloud Environment" wizard; best practice is therefore to use a name that easily identifies the cloud provider, such as "GoGrid" or "GoGrid (My Name)". The second page also includes settings specific to the cloud provider type which are described below.
The easiest way to run a Monterey application is through the Simulator. This is a mock network running on the local machine, which can be used to test applications without using a cloud provider's resources. In the simulator, all messages are sent over the network, so it is a faithful test in many respects apart from scale and throughput.
The configuration for a simulator account, shown above, has the following fields:
Preferred hostname: a hostname or IP address, or blank; used for all socket communications and also for the web-api. It is useful if there are multiple network interfaces and you want to choose one (e.g. if there is intermittent network connectivity, then using 127.0.0.1 for the simulator is advisable).
Monterey web-api port: the preferred port that the management node will listen on for its web-api
Custom locations URL: Specifies additional notional locations to be simulated. The file should be in the format described in the section Location Configuration. At a minimum, replace 'ssh-lab-mode' with 'simulator' and 'ssh.datacenter1' with 'simulator.datacenter1'.
The field is specified as a URL, so for a file must be of the form file:///<path>.
The simulator locations included out-of-the-box have the following location ids in Monterey:
For simulator, Calling MontereyLocation.getProvider() returns "simulator"
A cloud account for Amazon EC2 allows an end-user to deploy and run monterey applications on Amazon EC2. An AWS account is required, and these credentials must be supplied.
The cloud account wizard, shown above, is configured with these credentials. It has the following fields:
The standard set of Advanced Options is available, as well as the following extra options:
The amazon regions have the following location ids in Monterey:
For Amazon, Calling MontereyLocation.getProvider() returns "aws-ec2"
For a more detailed description of the amazon integration, see the Amazon AWS Integration section.
A cloud account for GoGrid allows an end-user to deploy and run monterey applications on GoGrid.
The cloud account wizard, shown above, is configured with the GoGrid credentials. It has the following fields:
The standard set of Advanced Options is available, as well as the following extra options:
The GoGrid data centers (see GoGrid's Data Centers page) have the following location ids in Monterey:
For GoGrid, Calling MontereyLocation.getProvider() returns "gogrid"
Configuring vCloud v1.01:
The cloud account wizard, shown above, has the following fields:
The standard set of Advanced Options is available.
For vCloud, Calling MontereyLocation.getProvider() returns "vcloud"
SSH Lab-mode will use a fixed pool of machines when provisioning and releasing Monterey management and network nodes. This same pool can be shared by multiple Monterey networks, from multiple users.
The list of machines is stored and maintained within a google spreadsheet. The spreadsheet should have the following columns:
The spreadsheet should have at most one row per publicAddress.
Note, if using a VPN to provide access, all addresses should be considered "public" because the VPN is ensuring that all relevant machines can communicate.
Note, the private address field is useful when some machines do not have a public address, but where there is a private address visible from within that network. In such a configuration, management nodes will always be placed on machines with public addresses; network nodes can use any machine. However, if the machine is not visible from outside the subnet then it cannot be used in an inter-cloud network - a solution is to use a VPN so that the same group of IP addresses or hostnames can be used throughout. Also note that if a machine has a different IP address from within the subnet than from outside, then it is recommended to configure DNS such that the hostname resolves correctly and then to use hostnames throughout.
The cloud account wizard, shown above, is configured with this google spreadsheet's name and the name of the worksheet within it. A google username (e.g. my.name@google.com) and password are also needed to access the spreadsheet - the account must have read/write permission.
Management and network nodes will be started and stopped by invoking scripts over ssh. The default ssh credentials (i.e. blank) will work if the user running studio has authorized_keys set up to be able to ssh in without requiring a password. Alternatively, the username to use can be set along with a particular private key file. For example, entering username myname and keyfile id_dsa will use the command::
ssh -i /home/myname/.ssh/id_dsa myname@<hostname>
The custom locations URL defines the location in which these machines will run. The URL should refer to a locations configuration file (e.g. file:///my/path/locations-datacenter1.conf). The file should be in the format described in the section Location Configuration.
The standard advanced options are available:
For Ssh Lab Mode, Calling MontereyLocation.getProvider() returns "ssh-lab-mode"
A common set of advanced options is available to customise the operation or usage of most types of cloud account. Any additional advanced options are described in the main section for each account type. The Appendix has further details on the Management Web API configuration options.
The standard advanced options are as follows:
The OK button will be disabled until valid options are entered in all fields.
You can drag-and-drop Monterey service projects onto cloud environments within the Clouds view. You can also drag-and-drop OSGi bundles (from within Eclipse or from the file system), or drag-and-drop a application descriptor file.
This will bring up a Deploy Monterey Application dialog. This allows you to select an application descriptor file, the projects to deploy, and any additional OSGi bundles to deploy. The dialog will be pre-populated with whatever was dragged onto it.
The drop-down list of application descriptor files is auto-populated with the configuration files found in the selected projects and bundles. Alternatively, you can browse the file system to select your descriptor file.
The projects listed will be deployed to the Monterey network. They will be automatically exported to generate OSGi bundles, and should therefore be Eclipse plugin-projects. The list of pre-built OSGi bundles will also be deployed. The projects and pre-built OSGi bundles should together contain the segment-service code, as well as any LPP code required.
To deploy, click Ok. This will launch a new Monterey network. A corresponding new entry will appear under the cloud environment.
Alternatively, you can open the deploy dialog by right-clicking on the cloud environment and selecting Deploy Application....
Instead of selecting projects to deploy, it is possible to manually generate the OSGi bundles. The standard deployment dialog can still be used, but selecting the pre-built OSGi bundles rather than the projects.
To create a bundle from your project:
To shut down a network, right-click on it and select Shutdown network. Note that you will not be able to do this if there are any running nodes in the selected network - you must first launch a Monterey Management Console and release all nodes in the network, before shutting down.
You can also remove a network from the clouds view without shutting it down or otherwise affecting it. Right-click and select Remove from list.
The run configuration for launching the Monterey simulator is deprecated - instead the Clouds View should be used. The run configuration, described below, will be deleted in a future major release.
Using either the Run or Debug menu, you can create a new Monterey Simulator run configuration. Then specify the application deployment descriptor file and click run.
The configuration also includes many other options similar to running any Eclipse Application. More information on these items is available in the Eclipse documentation, although in the normal course of using Monterey it is not necessary to edit these.
Monterey has some useful system properties, which include:
The Management Console provides a view of the running network, and allows an operator to made changes to the network.
The management console can be launched via studio as a Monterey Simulator or Monterey Deployment, or as a standalone application. If launched via the simulator, then for most use-cases you are ready go: next provision and rollout some nodes.
The standalone Monterey Management Console allows you to connect to a running management node, to view and manage that network.
The Resources View is the default view when opening the control pane. It shows a hierarchical view of the available resource locations, including all allocated nodes in the network. It includes the status and runtime details about each node:
The Nodes View shows the same resources in a sortable "flat" table, with additional details about runtime performance metrics:
Both views provide identical actions for provisioning and rolling-out nodes (see below), via their respective toolbar menus and right-click context menus.
The first step in creating a network is to provision some nodes. Right clicking on a location or click on the view's drop-down menu. From here you can select where to provision new nodes.
You can choose to provision a custom number of nodes, or use the quick setup in the menu. Each node is associated with a specific location, and this cannot be changed after allocation.
Note
In the simulator, the locations are London, New York and Tokyo. In production, the available locations are determined by the configuration of the management node. See Management Configuration Files for more information.
After a successful provisioning action, you can begin to use the nodes by rolling out the Monterey software. When allocated, the nodes are normally in a spare state, without a specific role within the network. Select All the nodes you wish to deploy to, and right click to bring up the context menu. The Roll-out option is now enabled and from here it is possible to either roll out a pre-set configuration, or set custom parameters.
There are four standard Node types: LPP (the gateway), MR (an internal router), M (the mediation node), and TP (an internal proxy). A typical network will have an equal number of each node type. If satellite/hubs are enabled (using bots { satellites true }), you can choose to roll out bots as well (these additional LPPs contain any client specific code in your gateway classes). Once you have rolled out to the spare nodes, they will appear in the network topology view.
Tip
It is is possible to quickly provision and roll-out a number of preset configurations. This can be done using the Quick Setup menu from the Resources View toolbar or right-click menu:
Note
The Satellite LPP, and its use in hosting bots, is currently under review, and is subject to change in the next release.
The Segment List View shows the current segments defined for the network. When the network is active, the per-segment statistics and run-time information can also be seen in the segment list. Each segment has an unique identifier, normally a short string; this is the only necessary property for a segment. Segments can be customized with a more descriptive name, and textual tags. Additionally, a segment has a color attached, used in the various graphs and charts throughout the management console. Colors can be set for a range of segments, using the context menu.
Note
Precisely which segments are displayed is determined by the currently deployed Monterey application. The following screenshots are based on the EZ-Brokerage reference application.
Tip
Setting one segment to a bright color makes it much easier to spot in the graphs and charts. Use the Hue option to set the color of a number of segments to similar but distinct shades of a given color.
It is also possible to do bulk operations on segments here by selecting the segments and using the context menu; for example migrating a group of segments to one particular Mediator.
Each node resides in a location. For the localhost provisioner these locations are notional, but for other providers the location will be used to distinguish between nodes in different "regions" of a cloud provider (using Amazon parlance), or data centers for a private cloud. or data centers.
The geography view shows the activity of nodes in each location, where locations are normally at the granularity of data centers (or clusters of data centers, such as Amazon's us-west-1). A circle on the map represents each location where there are nodes deployed. The area of the circle is indicative of the number of nodes deployed, and the color of the circle indicates the health of those nodes.
There is also a shadow cast upon the geography view, indicating the current Monterey clock time. This clock is used by some bots to adjust activity levels. You can change the current Monterey clock by dragging the shadow left or right to change the time of day. The current speed the clock runs at can also be changed here from the toolbar menu. More about the clock and bots will be covered further on.
You can use the geography view to filter the current graphs and views. Clicking on a circle will only display information for that specific location, and the titles of the views and graphs affected will change to reflect this. Clicking on the background will reset the views to showing all nodes as before.
Finally, when running in the simulator, it is possible to simulate latencies between locations. Using the Simulated Latency page, you can configure the delay in milliseconds between locations. When these values are changed, the new setting is used for all newly provisioned nodes; existing nodes will use the earlier settings.
The management console allows you to manually change the network topology and the location of segments, as well as allocate and deallocate nodes. In a real-world deployment, however, this should be done automatically, responding to changes in messaging volume, per-segment demand, regional activity shifts, and other factors.
Monterey Middleware supports custom management policies so that changes are made in response to these factors and according to the priorities (and budgets) of individual projects, to ensure the desired quality of service level throughout the network.
Monterey includes illustrative policies, which capture the following use cases:
"Follow the Sun" (optimise for latency): relocates segment data and processing to follow the locus of of active users, minimising average latency to the majority of customers. The policy detects high message rates in any given location for a given segment and will migrate the segment to the statistically busiest location.
"Follow the Moon" (optimise for cost): segments can be relocated to reflect changes in price linked to running the segment in a given location, with the goal to minimise costs. The policy can be kept appraised of relevant current prices, relocating segments to the cheapest available location.
Watermark Elasticity (optimise for usage): rolls out, reverts and re-routes nodes at a given location to optimise resource usage. High- and low-watermark settings guide migration and re-routing decisions, so that the policy keeps all nodes reasonably active (for resource efficiency) without any over-active (bottleneck) nodes. The policy will scale-out and scale-back from the pool of spare nodes, and can change the type of nodes based on the current usage pattern. This policy can be used in combination with the Node Pool Elasticity policy.
Node Pool Elasticity (optimise for usage): an auxiliary policy that grows and shrinks the number of nodes in a given location, based on requests for more nodes that are made by other policies.
The policy will scale-out (request new resources) and scale-back (give resources back) as needed and as permitted by the public or private clouds being used.
These policies can cut latency (and thus significantly improve the end-user experience) and reduce costs dramatically. This is true for globally-deployed applications, and also for applications in a private cloud where scaling out scaling back is desired.
Policies are shown and managed in the Policy View. To add a policy, right-click on the background of the table in this View. Right-clicking on any selected policy will allow you to suspend, resume, or remove the policy.
Some policies are available at different scopes, either regional or global. Regional policies are restricted to a specific location, while global policies work on the entire network. A common configuration is to enable the Watermark Elasticity policy in each region (e.g. doing load-balancing and scaling within a data-centre) and the Inter-Geography policy on the global level (it has no effect if it is applied to a single location).
Within the Preferences pane, operating parameters for these policies can be adjusted under Monterey Middleware -> Policy.
The Watermark Elasticity can be scaled to deal with less powerful machines or more computationally-intensive applications (numbers less than 1 decrease the watermarks).
The follow-the-sun policy has many more parameters for fine-tuning; assistance on each is available in the product in tool-tips which appear when the mouse hovers over each:
Follow-the-moon policies can be configured using the Costs Per Location preferences. This allows a cost function to be defined for each location. For example, the function below specifies that between 8am and 6pm the cost is 0.12 per hour, and between 6pm and 8am the cost is 0.06 per hour:
8-18h @ 0.12, 18-8h @ 0.06
It is also possible to exclude a given location from all inter-geography migrations. Segments will never be migrated into or out of excluded locations by follow-the-sun or follow-the-moon policies. This feature is accessible within the preference pane.
Node Pool Elasticity can be configured using the following parameters, which control when nodes should be released:
Custom policies can also be loaded and controlled through the Policies View. This allows a richer semantics of jurisdiction requirements or bespoke optimization strategies. For more information on creating a custom policy and initializing it, please consult the Appendix.
The basic management console views are:
All the basic views provide filtering (most support locational filtering and node type, where appropriate). You can also change the displayed columns in list views; both are accessible via the dropdown menu accessed via the arrow in the top right of a view area.
The management console supports deploying and undeploying applications. This is done through the Deployment menu.
Other options in the Deployment menu are "Describe application" for finding out about the currently deployed application, and "Reset management console". The latter will reconnect to the management node and re-initialize the management console's views (note that in simulator mode this has the side effect of stopping the entire simulated network).
See Deploying to a Monterey Network for further information on deployment.
The Monterey Management Console has a preferences pane for setting various configuration options.
For options that were set at startup, these are shown as immutable values in the preferences pane. For example, the "control plane location" is set automatically based on the way that the Management Console was started (e.g. the simulator always uses "Simulator (New Localhost Network)", whereas the standalone Management Console connects by default to a remote control plane over HTTP).
When connecting to an existing management plane, the preferences pane include the URL of a management node and the credentials to use when connecting.
There is an option to "force local IP", which controls the IP address used by the management console. This is useful when there are multiple network adapters.
"Workrate reporting period" controls how frequently the management console will retrieve network metrics, and thus how frequently the UI will refresh.
Under Monterey Middleware is the preferences page Policy that deals with policy settings. See Policies.
Monterey Middleware is designed so that its deployment and runtime management tools can integrate with toolsets at customer sites. Extensions as described under Command-Line Deployment can permit other toolsets to be used for allocating, provisioning, and scale-back, and a management API for the management console allows Monterey to be managed from other front-end consoles.
Note
This functionality is not available in the evaluation version of Monterey Middleware. Please contact Cloudsoft for further information.
Monterey applications are intended to run in a large-scale, distributed environment, and the processes for deploying and managing are almost identical to those used for the Simulator. The Management Console and API described in the previous two sections can connect to a remote Monterey network and all functionality is the same.
This section describes how to set up a Monterey network, deploy an application to it, and start the Management Console (or API).
A Monterey network is configured with several network nodes and a single management node.
The developer/deployer interacts with the Monterey network via the Management Console running on their local workstation, connected to the management node over HTTP. To provision a node for use within the Monterey network, the management node connects to it over SSH and runs the appropriate scripts that were installed when the machine was set up (see below). Only the management node is required to be addressable from outside the network (i.e. from the developer/deployer's workstation).
The unpacked Monterey Studio download package contains archives for installation on the machines (which may be "bare-metal" hardware or VMs) that will comprise the Monterey network infrastructure.
It is best practice to run a single network node per (virtual) machine.
It is possible to run multiple network nodes on a single machine. You may find this configuration useful when you want test your application in an environment that is closer to a production environment, but without requiring a large number of machines to set up a production network. Please note the limitations of this configuration:
Setup steps:
Make a copy of the monterey-network-node directory for each additional node required:
cp -r monterey-network-node monterey-network-node-1
Change the port (8023) in monterey-network-node-1/scripts/osgi-network-node-start.sh to a free port value for each copy.
Ensure that the run user can ssh to each aliased host via passwordless SSH.
For configuring a cloud account of type SSH Lab-mode:
Setup the machine hosts file (e.g. /etc/hosts) with an alias for each hostname to be used.
127.0.0.1 localhost host1.tokyo.example.com
Add a separate entry to the SSH Lab-mode spreadsheet for each network node.
Note
ssh is used to communicate between the Management Node and the Network Nodes. Microsoft Windows users will need to perform additional steps (such as setting up cygwin) in order to sucessfully use these node types.
A series of plaintext username:password[,role ...] entries, one per line, that restricts access to the management node's web API. This is a standard jetty configuration file (see http://docs.codehaus.org/display/JETTY/Realms). It therefore supports passwords in plain text, obfuscated (prefixed OBF:) and encrypted (prefixed CRYPT:, whose value can be generated using UnixCrypt.crypt).
There are two roles defined for controlling access to the management web API: admin and client. The admin role has full access; the client role can only register and unregister external LPPs.
An example file is:
andy: CRYPT:zl0h9MdBtm/RY,admin guest: password,client
The monterey network can be configured to use a message bus for control messages. This will be used by nodes for publishing their state (e.g. changes of node type, segment migration, etc).
The message bus to use can be configured in management.conf. For example:
managementBusBundle=com.cloudsoftcorp.monterey.activemq managementBusCommsFactory=com.cloudsoftcorp.monterey.activemq.comms.ActiveMqPubSubCommsFactory managementBusAddress=tcp://management-node:61616 broker-token
The token management-node must be replaced by a valid address (hostname or numeric) that is accessible from all the network nodes.
For starting a simple ActiveMQ message bus, there is a script included with monterey-management-node. For example, run:
./start_activemq_broker.sh broker:tcp://management-node:61616/
This will configure the nodes to publish to the ActiveMQ broker, and for the management node to subscribe to those messages.
Other types of message broker can also be used. This involves configuring the management.conf with an OSGi bundle containing a monterey message integration. Contact your cloudsoft representative for further details.
Monterey applications can be deployed to distributed Monterey networks as easily as running them in the simulator. The recommended way is to use the clouds view, such as the ssh lab mode.
The following approach is deprecated:
Before deploying, the uninitialized network should be available, with a management node running able to provision network nodes, and the OSGi bundles for your application installed on all nodes. Then, to deploy, create a Monterey Deployment launch configuration, just as was done previously in the Monterey Simulator section: the only difference is that along with the application deployment descriptor file, the configuration requires the details for accessing a management node in the target Monterey network.
If there is already an application running at that management node, then an error dialog will be displayed saying that deployment failed. Only one application can be deployed on a given management node at a time.
Undeploying and deploying applications can be done through the "Deployment" menu of the management console. To undeploy an existing application, there must first be no nodes running. The "undeploy" action will then remove the application from the management node.
The "Deploy application" menu option allows an application to be deployed to the management node. The user selects a deployment descriptor file, which is then sent to the management console. If an application is already deployed, this action will fail.
It is possible to deploy applications from the command-line by running the Management Console executable "headlessly" with some additional parameters as follows:
path/to/MontereyManagementConsole \ -deploy application=path/to/DeploymentDescriptor.conf \ bundles=path/to/bundle1.jar,path/to/bundle2.jar \ management.url=http://monterey.example.com:8080/ \ management.user=username \ management.password=password \ -noSplash
Or, under Mac OS/X:
path/to/MontereyManagementConsole.app/Contents/MacOS/MontereyManagementConsole \ -deploy application=path/to/DeploymentDescriptor.conf \ bundles=path/to/bundle1.jar,path/to/bundle2.jar \ management.url=http://monterey.example.com:8080/ \ management.user=username \ management.password=password \ -noSplash
Similarly, it is possible to undeploy as follows:
path/to/MontereyManagementConsole \ -undeploy management.url=http://monterey.example.com:8080/ \ management.user=username \ management.password=password \ -noSplash
Resilience modes are discussed in more detail in the Developing for Resilience section.
Run-time resilience options are configured in the application descriptor using the syntax:
resilience ResilienceMode.NONE
or
resilience ResilienceMode.CHECKPOINT, replicas:1
or
resilience ResilienceMode.LOSSLESS, replicas:1
The replicas parameter specifies how many nodes should be sent a copy of the data. When there are n replicants, there is (n+1) resilience: if all (n+1) nodes fail then all copies of the data will have been lost. However, the larger the value of n the greater the impact on performance.
For replicating segment state, the replicant nodes used are other mediators. In the event of a node failure, a replicant for each of the affected segments will be automatically promoted. For LPPs, the replicant nodes are of type LPP_BACKUP. These LPP_BACKUP nodes must be started explicitly.
In some situations other strategies may be more appropriate and can be developed by arrangement with Cloudsoft. In particular where persistent/reliable messaging is used for point-to-point communications or an underlying virtualization layer offers disaster recovery capabilities, the redundancy offered by these components can reduce or eliminate the demands on resilience at the Monterey level. However in many situations Monterey is the most efficient level at which to maintain the redundancy, and significant performance and efficiency gains can be achieved by bypassing resilience in underlying components.
Limitations
For NONE and CHECKPOINT resilience modes, it is possible for messages to be lost when nodes fail. In the case of checkpointing, everything processed before the last checkpoint will have been saved.
In auto-resilience, delivery of broadcast messages is not guaranteed in the event of node failure.
Currently, lossless resilience is only available in classic mode and not with the service development interface-based approach.
Moving to a live environment requires careful planning and review of several additional issues, as well as a migration to a production Monterey platform. There are no code changes necessary; the API is supported on our production platform. However there are a variety of other issues which have to be considered, including management, security, and resilience.
The evaluation version of Monterey Middleware is not permitted for use in production or live applications. Production features are not enabled. The information in this section is provided for reference only. Please contact Cloudsoft for further information.
Hot code swapping describes the situation where it is necessary to update code which is running without interrupting service. In many other platforms this requires extra implementation or special facilities, if it is supported at all. However using application mobility provided by Monterey it is possible to update live code seamlessly.
As with ordinary migration, the current mediator is told to shutdown, and the state sent to a new mediator on the network. Unlike a normal migration, however, the new mediator is running a newer version of the code. This hot code swap is transparent to the clients, just as with ordinary migration, and the sequential ordering of messages is preserved.
Note
This functionality is not available in the evaluation version of Monterey Middleware. Please contact Cloudsoft for further information.
Security at the communications layer in Monterey Middleware can be ensured by using either HMAC-SHA-1 authentication (for each message) or SSL certificates and encryption (for each connection), depending on requirements. This can be applied on a per-path basis. It is also possible to configure Monterey to use a custom transport (such as a messaging system or IPsec VPN) to comply with site-specific requirements or for additional security. This can be done in conjunction with HMAC or SSL. The management node can be supplied with a JKS keystore containing an SSL certificate, in order to secure Management Web API communications using HTTPS instead of the default, HTTP.
At the application layer Monterey can enforce Java permissions; this is principally useful when the code running on the Monterey is potentially untrusted.
At the infrastructure level, Monterey can be locked down by firewall or iptables rules such that only the LPP client nodes are externally addressable, and such that these nodes are only accessible on the ports used by the application-specific client gateway code. For example, with an application whose client gateway launches a web server on port 8080, Monterey can run on a private subnet with an external firewall forwarding traffic to the web servers only. Communications within the Monterey network uses only non-root ports numbered 1025 or higher; it is not necessary to enable any services on lower numbered ports. It is not necessary that the Monterey nodes be able to contact the internet, unless the application-specific LppClientGateway and MediationSegmentService require it.
Note
This functionality is not available in the evaluation version of Monterey Middleware. Please contact Cloudsoft for further information.
By default, the Monterey nodes and Management Console will open a port to accept incoming connections from a remote OSGi console, which can be very useful when diagnosing problems with OSGi bundles at runtime. This is achieved by specifying the -console <port> argument in the startup scripts. If desired for security reasons, this can be removed without affecting the operation of the network or deployed application.
An AWS account is required to deploy and run on Amazon AWS. Appropriate credentials must be supplied prior to deploying the application. The following Amazon security information is required:
The easiest way to setup a security group is to use the Amazon EC2 API Tools.
You will need to install the Amazon EC2 API Tools, which can be downloaded here.
Next, configure the EC2 API Tools. These commands will work for bash and similar shells:
export AWS_ACCESS_KEY_ID=access_key_id_from_step_2 export AWS_SECRET_ACCESS_KEY=secret_access_key_from_step_2 export EC2_CERT=certificate_file_from_step_3 export EC2_PRIVATE_KEY=private_key_file_from_step_3 export EC2_HOME=location_where_ec2_api_tools_are_installed export PATH=$EC2_HOME/bin:$PATH
Now for each region - eu-west-1, us-east-1, us-west-1, ap-southeast-1 and ap-northeast-1 - create a security group (we recommend calling it monterey) and specify the firewall ports that Monterey requires:
export EC2_REGION=<region> export EC2_URL=https://$EC2_REGION.ec2.amazonaws.com ec2-add-group monterey -d "Monterey Middleware" ec2-authorize monterey -p 22 ec2-authorize monterey -p 8080 ec2-authorize monterey -p 8443 ec2-authorize monterey -p 43500 ec2-authorize monterey -p 43501
This completes the required configuration.
Applications written in Monterey can be deployed and run on Amazon AWS.
The locations available in Monterey correspond to the Amazon regions: US-East (Northern Virginia), US-West (Northern California), EU-West (Irelend), Asia Pacific-South East (Singapore) and Asia Pacific-North East (Tokyo).
When deploying an application, a VM is automatically provisioned to run a management node. When network nodes are subsequently started, a VM is automatically provisioned for each. Cloudsoft supply AMIs for creating these management and network node VMs.
Interaction with Amazon and the VMs is through a combination of web-service calls and SSH.
The instances created from the Cloudsoft AMIs contain no special SSH configuration. The only way to log into the instance is to supply your private ssh key file. For example:
ssh -i ~/.ssh/id_rsa-myname.us-west-1 ec2-184-72-171-85.compute-1.amazonaws.com
Under the covers, deploying and running an application on AWS involves the following steps:
You can view the running VMs in each region by logging on to the AWS Management Console.
VMs will be tagged with three values: a Node Type to indicate whether a VM is a management or a network node, a Version indicating the version of Monterey Middleware they're running (taken from the AMI they were built with) and an optional Network ID which can be provided when launching the management console; the Clouds view automatically populates the Network ID to match the one displayed in the view, while the management node will automatically configure any nodes it provisions with a matching ID.
Click on the small arrow at the top right of the The Clouds View and select New Cloud Environment... This will start the New Cloud Environment Wizard. Select Amazon from the list of cloud environment types and click Next.
The Amazon service configuration page contains the following fields:
Clicking Finish will then create the new cloud environment for Amazon. The Amazon AWS credentials and other settings will be verified and, if there are no problems, the new cloud environment will appear in the Clouds view. You can now deploy applications to Amazon EC2 as described in The Clouds View.
Application fails to start
There are numerous interdependencies any one of which being slightly wrong can cause an application, either Monterey Studio or your own Monterey Application from the management console, not to start. Following are some common causes and tips for resolving this:
Error message: java.lang.UnsatisfiedLinkError: Cannot load 32-bit SWT libraries on 64-bit JVM
If you are in a mixed 64- and 32- bit environment it may be necessary to force a particular architecture. This can be done by passing the Java VM argument -d32. When launching from within studio, add this to the launch configuration, in the Arguments tab, by adding -d32 as a VM argument. When launching the standalone Management Console, edit the .ini file.
Within Eclipse, you can add this as a default VM argument for whenever you launch Java: in Preferences, navigate to Java -> Installed JREs, then select your chosen installed JRE and click Edit, then add the Default VM Argument of -d32.
With OS X it can be particularly complicated because some versions of Apple's Java 1.6 are 64-bit only. Check you are up-to-date with OS X Updates as the newest versions do include both 32-bit and 62-bit JVMs. Installing Java 1.6 supporting 32- and 64-bit can help (although this is not supported by Apple), as can forcing the OSGI arch to be x86_64.
Error message: java.lang.UnsatisfiedLinkError: Cannot load 64-bit SWT libraries on 32-bit JVM
If you are using the 64-bit version of Monterey Studio with a 32-bit JVM it may be necessary to force a particular architecture. This can be done by passing the Java VM argument -d64. When launching from within studio, add this to the launch configuration, in the Arguments tab, by adding -d64 as a VM argument.
On Mac OSX, Java compiler errors: ...only available if source level is 1.5 or: Unbound classpath container: 'Default System Library'
A recent Apple Java Update modified how Java Virtual Machines are installed and configured, and the current versions of Eclipse are unable to detect the new configuration. Eclipse either falls back to assuming Java 1.4 as the default JVM, or no default JVM at all.
You must must manually identify the correct JVM that Eclipse or Monterey Studio uses as default. Open the Preferences dialog, and go to the Java -> Installed JREs pane. This should list a number of JVMs from versions 1.4 to 1.6 (or later) - if it does not, click the Search button. Then, ensure that an appropriate JVM is ticked to indicate it is the default JVM - we require a JavaSE 1.6 JVM. Click OK.
If there are still errors: open Preferences and go to the Java -> Compiler pane. Ensure the Compiler compliance level is set to the same Java version as selected earlier. Click OK. If problems persist, right-click on a project with errors and select Properties. Go to the Java Compiler pane. Ensure that either Enable project specific settings is off, or that the Compiler compliance level is set to the same Java version as selected earlier.
Error message: Queueing viewer updates
This message appears in some environments from time to time. This is a known Eclipse bug and does not seem to cause any problems apart from irritation. Restarting the application and doing fewer memory-intensive activities in the application can help. We are actively looking for a solution.
Monterey Application fails to run locally (in Simulator)
The Studio contains a Console view which will contain logging information for the simulation run. In some cases, Simulator will cache data from the Monterey Application environment. In the launch configuration dialog there are options to ensure that it cleans the workspace and the configuration area; enabling these may help. The OSGi console is available for additional debugging and exploring on port 8021, for example using the unix command nc 8021.
Monterey Application fails to run remotely
Check that the remote network is available and that the OSGi bundles for the Monterey Application have been correctly installed there. OSGi can cache data so it may be necessary to remove the monterey-network-node directory and re-install if the application has been changed. (In some situations, OSGi containers can be started with -clean to clear its cache; consult standard OSGi and Eclipse Equinox references for more information.)
Monterey Application does not shut down cleanly
Monterey runs as a distributed application, even if only running on localhost, and while Monterey attempts to progress and orderly shutdown, it may not complete in time (particularly when the management console is launched from within Monterey Studio). Errors or warnings may be displayed, or some non-daemon node threads may be left running (preventing the application from shutting down). In all cases it is safe to forcibly terminate the application from within Eclipse (clicking the red "stop" button) or at the OS level.
Nodes do not start when using ActiveMQ
ActiveMQ tries to resolve the node's hostname to an IP address during initialization. This may not be the case on some Linux configurations and/or if the node is not registered in DNS. You can test this using the hostname and ping commands. For example:
$ hostname node-53 $ ping -c 1 node-53 PING localhost (127.0.0.1) 56(84) bytes of data. 64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.010 ms ...
If the ping command returns unknown host instead, then you should ensure that the node is correctly registered in DNS or that the hostname is added to /etc/hosts (an address of 127.0.0.1 is acceptable for the hostname and is easier in some virtualization environments).
NoClassDefFoundException for types in packages javax, org.xml.sax, etc. The OSGi container will add an implicit Import-Package for all of the java.* packages provided by the JRE. For JRE classes that are not under java.*, the OSGi container will provide these for bundles that request them, but they are not automatically available. If your bundle depends on any JRE type that is not under java.*, you must explicitly declare this in your MANIFEST.MF using the Import-Package directive. For example:
Import-Package: javax.servlet, javax.servlet.http
Rollout Globally and Activate Bots - bots activity level stays at zero. When using the management console and selecting the option to "Rollout Globally and Activate Bots" sometimes the bot activity level remains at zero. If this happens, the desired bot activity level and profile can be set by using the Bots view.
Error message: Cannot find Object class referenced by required class files
This appears as an error against the first line of source code if Eclipse is improperly installed. The most common causes are that the application is missing plug-ins (specifically JDT) or there is no compatible Java Development Kit found.
Error message: Failed to find OSGi service for monterey-mediator-factory
This appears when starting a mediator and the OSGi service required to instantiate the application's code cannot be found. This OSGi service is by default defined using xml declarative services in the META-INF/OSGI-INF directory. This file must declare a valid OSGi service and the names must match those used in the application descriptor configuration file. You can see which OSGi services are registered on a given node via the OSGi console (port 8023 by default on a network node). The following are some common causes and tips for resolving this:
Error message: Failed to find OSGi service for monterey-lpp-factory
This is a similar error to the previous one for monterey-mediator-factory. It occurs when the OSGi service for the instantiating the application's LPP code cannot be found. See the suggested steps above, except that the provided interface should be com.cloudsoftcorp.monterey.network.api.LppClientGatewayFactory, and the OSGi service component name should match the clientGateway value in the application descriptor configuration file.
Error message: Command failed: java.net.SocketTimeoutException: Read timed out
When executing actions through the management console, such as provisioning and rolling out nodes, there is a timeout for waiting for a response from the management node. When this time elapses, the management console will stop waiting for a response and will display this message. The timeout can cause the rest of the action to be aborted (e.g. when using quick-setup to create a new cubic, if it times out provisioning the nodes then those nodes will not be rolled out). However, any parts of the action that started executing on the management node will continue to execute. Consult the logs on the management node for any errors or other explanations why the command might take so long.
JRE Container or Execution Environment problems
Depending on your OS and installed version(s) of Java, Eclipse may show warnings about the JRE Container on classpath not being a "perfect match" to the application environment. We are using Java 1.6 (or higher), and while Eclipse can detect that it is a match, it requires you manually to approve a "perfect match" to get rid of these warnings. This can be done by opening Preferences -> Java -> Installed JREs (Preferences can be found under either the Monterey Studio or the Window item in the menu, or by pressing ctrl-comma) and selecting a 1.6-compatible JVM, then by opening the Installed JREs -> Execution Environment node, selecting the JavaSE-1.6 environment and on the right-hand side, choosing the JVM you just selected.
Warning message: Serializable class does not declare serialVersionUID
Java recommends that Serializable classes provide this private static field. This is not necessary for Monterey, so you can disable this warning in the Preferences; or you can use the Eclipse Quick-Fix (Ctrl-1) to do create such a field for you.
The RESTful web API supports remote management of a network. Queries can be made to get information about the network, and modifications can be made to the network. For example, a customer could implement a policy that monitors and manages the network according to a customer's business needs, solely using the web API.
The web-api settings and login credentials are as defined when starting the management node, and are logged by the management node when it starts (by default, these are in web.conf and web-users.conf with default credentials guest:password and using http on port 8080).
The Web API can be protected using SSL/TLS via the HTTPS protocol. To use this feature, the protocol must be changed from http to https in the Advanced Options... dialog of the cloud account configuration wizard. The web-api uses Jetty to serve content, and the SSL configuration page <http://docs.codehaus.org/display/JETTY/How+to+configure+SSL> on the Jetty site describes how to create and use a keystore when using the https protocol. Since the keystore is also used by the network nodes as a truststore when communicating with the management node using the web-api, it must also contain the public key of the certificate used for signing as well as a signed private key. At a minimum, the keystore should contain a self-signed certificate to allow https communication.
For the example here, we use http://localhost:8080/, but you should substituted whatever actual management node DNS name, protocol and port is configured in your cloud account properties.
- http://localhost:8080/root/status/nodes
List all node IDs.
Note: the representation of a node id is not intended for human consumption - its primary purpose is to allow the IDs to be passed in subsequent web calls.
- http://localhost:8080/root/status/nodes?type="MR"
- List node IDs for nodes of a given type. Valid values are: LPP, MR, M, TP, SATELLITE_LPP, SPARE and LPP_BACKUP.
- http://localhost:8080/root/status/nodes/summary
- List a summary of each node.
- http://localhost:8080/root/status/nodes/topology
- Says which nodes are connected to which. For example, for each LPP it indicates the MR it is connected to.
- http://localhost:8080/root/status/segments/summary
- List all segments, giving a summary of each.
- http://localhost:8080/root/status/segments/allocation
- Get the mapping of segment to mediator, indicating where each segment is mastered.
- http://localhost:8080/root/status/locationTree
- List the locations available for running nodes, and the usage/capacity at each.
- http://localhost:8080/root/status/activityModel/machineLoad
For each node, gives the load on that machine (CPU usage and other metrics).
Note: there is an optional 'node' parameter, where the value is in the JSON format returned by /status/nodes. For example, http://localhost:8080/root/status/activityModel/machineLoad?node=...
- http://localhost:8080/root/status/activityModel/workrate
- For each node, gives metrics about the node's workrate.
The following requests retrieve information about policies.
- http://localhost:8080/root/policy/extantPolicies
- Show policies that have been instantiated and not disposed.
- http://localhost:8080/root/policy/availablePolicies
- Describes the types of policy that are available.
The following requests make modifications, so must be done with HTTP PUT.
- http://localhost:8080/root/policy/instantiate?config=...
- Instantiates and starts a new policy. The config parameter is a JSON-serialized PolicyConfiguration instance.
- http://localhost:8080/root/policy/dispose?id=...
- Removes the policy with the given ID, where the ID matches one returned by extantPolicies.
- http://localhost:8080/root/policy/suspend?id=...
- Pauses the policy with the given ID, where the ID matches one returned by extantPolicies.
- http://localhost:8080/root/policy/resume?id=...
- Resumes the paused policy with the given ID, where the ID matches one returned by extantPolicies.
The following HTTP requests modify the network. They must therefore be done with HTTP POST.
- http://localhost:8080/root/controller/rollout?type="MR"&count=1&location=...
Where type can be any of LPP, MR, M, TP, SATELLITE_LPP, and LPP_BACKUP.
The count parameter can be any positive integer.
The location parameter is optional; it should be of the form: "com.cloudsoftcorp.util:com.cloudsoftcorp.util.resource.basic.BasicResourceLocation(\"/London\")"
- http://localhost:8080/root/controller/setWorkrateReporting?period=1000
- Where period is the duration in milliseconds between reports.
- http://localhost:8080/root/controller/provision?count=1&location=...
The count parameter is the number of nodes to provision.
The location parameter indicates where those nodes should be provisioned.
- http://localhost:8080/root/controller/migrateSegment?segment="ibm"&node=...
- The node parameter identifies the new mediator node.
- http://localhost:8080/root/controller/switchoverRouter?node=...&router=...
- The node parameter is the source-node, which is to be rewired to the given router.
- http://localhost:8080/root/controller/offload?node=...
- Moves all work from the given node to other nodes, where possible. For example, a mediator will migrate its segments elsewhere, an MR will reroute any LPP to other MRs, etc.
- http://localhost:8080/root/controller/revert?node=...
- Reverts the give node so that it becomes "spare".
- http://localhost:8080/root/controller/release?node=...
- Shuts down the given node.
- http://localhost:8080/root/controller/addSegments?segments=...
- Creates the given segments. The segments parameter is a JSON collection of SegmentSummary instances.
The locations used by Monterey are defined in location configuration files. These locations are visible in the Monterey Management Console's resources view, in the geography view, and also by policies when deciding where to start/stop nodes, migrate processing, or change routing.
An example locations file is shown below. This is groovy code. The format is considered experimental, so may change in subsequent releases.:
locations {
"ssh.datacenter1" {
displayName "Hawthorne-NY Datacenter"
abbr "ssh.dc1"
iso3166Codes "US-NY"
timezone "America/New_York"
provider "ssh-lab-mode"
providerLocationId "montereyEast"
metadata("cloudsoft") {
montereyProviderId "ssh-lab-mode"
montereyNormalisedCoordinates ([0.295, 0.413])
}
}
}
These fields are explained below:
In addition to the Monterey platform software, it is useful to configure the following software on the machines (be they bare-metal or virtual machines) that will host the Monterey network and management nodes.
Unnecessary services should be disabled (daemons and ports); iptables is configured to allow access to ports on the subnet (or disable iptables altogether, especially if you're behind a firewall and want lower latency).
We recommend XenServer 5.5 for the hosts; as there is no requirement for XenServer Essentials, the freely-available version is sufficient.
It is recommended to allocate a core to each VM on the hosts. Create the many identical VMs by from a 'master' VM (see above) that is exported, copied to all hosts, and re-imported as many times as necessary on each.
The master VM was created from one of the standard Xen templates (we primarily use 32-bit Debian Etch but have also had success with 64-bit Centos 5.3).
In addition to the generic policies included with the Monterey Middleware platform, the user policy API permits custom management logic to be written in Java and dynamically injected into a Monterey network.
Each policy conforms to the UserPolicy interface:
public interface UserPolicy {
/** The full name of the policy. */
String getName();
/** Starts (or restarts) the policy. */
void start();
/** Pauses the policy; can be resumed with start(). */
void suspend();
/** Deletes the policy. */
void dispose();
}
User policies are instantiated on demand through a separate factory class that conforms to the UserPolicyFactory interface:
public interface UserPolicyFactory {
String getName();
UserPolicy newPolicy(KeyValuePairList<String, String> properties, UserPolicyHelper helper);
KeyValuePairList<String, String> getProperties();
}
The factory provides a name which is displayed in the Management Console to identify the corresponding policy type. Although it is not mandatory for this to reflect the name of the policy created, it is certainly good practice for it to do so.
UserPolicy implementations interact with the network through a separate UserPolicyHelper instance, which is typically provided at construction time (by the factory) and cached for later use. This object is responsible for ensuring that network mutations are properly synchronized and isolated from one another, by permitting changes only within the scope of a NetworkAction class. The flow of control between the UserPolicy and NetworkAction proceeds as follows:
Note
The NetworkHandle instance is only valid for the duration of the NetworkAction.run method.
An illustrative, if not very useful, network action is shown below, which migrates each of the network's active segments to a different (randomly-chosen) mediator:
NetworkAction randomMigrationAction = new NetworkAction() {
public void run(NetworkHandle handle) {
Collection<NodeId> mediators = new ArrayList<NodeId>();
mediators.addAll(helper.getNetworkInfo().getAllMs());
for (String segment : helper.getNetworkInfo().getAllSegments()) {
NodeId currentMediator = helper.getNetworkInfo().getSegmentAllocation(segment);
mediators.remove(currentMediator);
NodeId targetMediator = CollectionsUtils.getRandomElement(mediators);
mediators.add(currentMediator);
handle.migrateSegment(segment, targetMediator);
}
}
};
helper.runAction(randomMigrationAction);
Tip
As in this example, concrete NetworkAction classes will typically be implemented as (possibly anonymous) inner classes to permit them access to the enclosing policy's cached UserPolicyHelper instance.
To use a custom policy, you must do three things:
The custom policy must be packaged as an OSGi bundle. For more about OSGi and its use in Monterey, see OSGi. Otherwise, see the instructions below.
Create an OSGi bundle containing the policy factory - a plugin project within Eclipse is an OSGi bundle. A bundle may contain any number of policy factory services. Each factory must then be registered as an OSGi service so that management nodes can discover it at runtime. This can be done using an activator or using declarative services. The New -> Component Definition wizard makes this step easy. The xml for a declarative service is shown below:
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="my policy">
<service>
<provide interface="com.cloudsoftcorp.monterey.network.control.userpolicy.api.UserPolicyFactory"/>
<provide interface="com.example.MyPolicyFactory"/>
</service>
<implementation class="com.example.MyPolicyFactory"/>
</scr:component>
The declarative service must be advertised in the bundle's META-INF/MANIFEST.MF:
Service-Component: OSGI-INF/my-policy.xml
The application descriptor configuration file should be modified to ensure that the bundle is started on the management nodes. If the policy is in a bundle named com.example.monterey.policy, the following entry will activate it:
bundles {
management {
activate "com.example.monterey.policy"
}
}
The deployment procedure for a policy bundle is the same as for any Monterey plugin. For example, on deployment the project can be dragged-and-dropped along with the rest of the application's bundles. See Application Deployment in the OSGi section of the manual for further instructions.
The policy will then be found in the Policies view of the Management Console.
Monterey applications and user policies are written and deployed as OSGi bundles.
OSGi has become the de-facto standard dynamic module system for Java. Modules, or bundles, can be installed into an OSGi container and can be started and stopped, updated and uninstalled all without requiring the container to be restarted. Each bundle is an ordinary Java jar file with some special meta-data. OSGi also has a service registry, which allows bundles to advertise services, and to obtain service implementations contributed by other bundles.
A bundle typically registers its services when it is activated; this can be achieved either through the inclusion of additional meta-data files (according to the OSGi declarative services specification), or by the provision of a BundleActivator that is will be instantiated and called automatically by the OSGi container when the bundle is activated.
Each bundle has a META-INF/MANIFEST.MF file. This defines the symbolic name of the bundle, which in Eclipse normally matches the project names. The manifest file can also include a reference to an activator class and/or to a set of declarative services files (e.g. Service-Component: META-INF/OSGI-INF/*.xml). The MANIFEST.MF file includes many other things such as the bundle's dependencies (i.e. the bundles that must also be installed) and the exported packages (i.e. the Java packages in that bundle that are visible to other bundles).
Declarative services allow services to be declared in XML files. When the bundle starts, the service defined in the file is automatically instantiated and registered. Below is an example of a declarative service:
<component
name="com.acme.chatroom.monterey.gatewayFactory"
xmlns="http://www.osgi.org/xmlns/scr/v1.1.0">
<service>
<provide interface="com.cloudsoftcorp.monterey.network.api.LppClientGatewayFactory"/>
</service>
<implementation class="com.acme.chatroom.ChatroomClientGateway$Factory"/>
</component>
The implementation class is the class that is to be instantiated. The provide interface is the type of service, and the component name gives a logical name for this component that can be used when looking up the service.
The OSGi container is a program that manages a set of bundles. Monterey Middleware uses the popular Equinox container. When the Equinox container is run, it reads a config.ini file which defines a set of bundles and says which of these should be started. Equinox also offers some conveniences to install all bundles contained within the plugins directory and to register the declarative services in any bundle that is started.
The OSGi Console allows a user to manage the bundles and services. The Monterey management nodes and network nodes can allow an OSGi console to connect remotely (on port 8022 for management nodes and 8023 for network nodes). The command nc localhost 8022 will open a connection. Some useful commands are as follows:
- ss
- Lists the "short status" for all known bundles, including the ID and state for each.
- status
- Lists more verbose information about known bundles and services.
- start 32
- Attempts to start the bundle with ID 32.
- stop 32
- Stops the bundle with ID 32.
- diag 32
- Reports ("diagnoses") any problems with the specified bundle that will prevent it from being started by the container.
Applications to run on Monterey Middleware must be packaged as OSGi bundles.
An application must define and register OSGi services that can create instances of LppClientGateway and MediationSegmentService for use on LPP and mediator nodes. We recommend that declarative services are used for registering these services.
The first service must implement the interface com.cloudsoftcorp.monterey.network.api.LppClientGatewayFactory, and must be registered with that interface name. It must also define a component name that can be used in the application deployment descriptor file. Similarly for the second service, it must implement the interface com.cloudsoftcorp.monterey.network.api.MediationSegmentServiceFactory and must be registered with that interface name, and it must define a component name. One or more MediationSegmentServiceFactory service can be registered. It is the job of the application deployment descriptor author to choose which service to use for which segments.
Here is an example taken from the chatroom tutorial. First, a MediationSegmentServiceFactory is defined that can instantiate a MediationSegmentService:
package com.acme.chatroom;
public class ChatroomSegmentService implements MediationSegmentService {
public static class Factory implements MediationSegmentServiceFactory {
public MediationSegmentService newSegmentService(String segment) {
return new ChatroomSegmentService();
}
public SegmentStateBackup newSegmentBackup(String segment) {
return null;
}
}
...
}
Next, an XML file in META-INF/OSGI-INF/serviceFactory.xml declares this as a service. It gives the service instance the name com.acme.chatroom.monterey.serviceFactory:
<?xml version="1.0" encoding="UTF-8"?>
<component
name="com.acme.chatroom.monterey.serviceFactory"
xmlns="http://www.osgi.org/xmlns/scr/v1.1.0">
<service>
<provide interface="com.cloudsoftcorp.monterey.network.api.MediationSegmentServiceFactory"/>
</service>
<implementation class="com.acme.chatroom.ChatroomSegmentService$Factory"/>
</component>
The META-INF/MANIFEST.MF has a clause that ensures this file will be used to define an OSGi declarative service:
Service-Component: META-INF/OSGI-INF/*.xml
The application deployment descriptor file identifies this named service as the one to use for all segments. This is done with the line:
segmentService "com.acme.chatroom.monterey.serviceFactory"
Assuming that the application's project is called com.acme.chatroom and that this matches the bundle's symbolic name, then the descriptor file also declares this bundle:
bundles {
application {
activate "com.acme.chatroom"
}
}
If the node is rolled out as a mediator, the bundle is started which causes our service to be instantiated and registered. Monterey Middleware can then lookup the service using the component name defined in the deployment descriptor; under-the-covers it uses the standard OSGi service lookup technique:
bundleContext.getAllServiceReferences(
"com.cloudsoftcorp.monterey.network.api.MediationSegmentServiceFactory",
"component.name=com.acme.chatroom.monterey.serviceFactory");
When the bundle is reverted or released, the bundle is automatically stopped if it was started during rollout.
Once the OSGi project has been created, there are two ways to deploy it. The project can either be deployed directly from the clouds view or it can first be built into a jar.
To launch directly from the clouds view, select your plugin projects in addition to your application projects and drag to a cloud environment in the clouds view. The OSGi bundles will then be built automatically and deployed to the Monterey network.
You can also package a project as a jar for later use. To create the jar from Monterey Studio, right click on the project and select export. Open the "Plug-in Development" folder and chose "Deployable plug-ins and fragments". In the resulting wizard, ensure that your project is ticked, along with any additional projects it requires. Provide a destination directory when prompted, and click "Finish". The wizard will generate a jar file per project in a "plugins" sub-directory of your specified location; these jar files are the OSGi bundles. The jar files can then be deployed in the same manner as before - dragging to a cloud environment.
Alternatively, bundles can be installed on the network nodes manually. Simply copy them into the plugins directory of the monterey-network-node installation. When the network node is started, the bundles will be installed.
Some customers may wish to configure a VPN, for example that spans a public cloud and their private data center. There are a number of ways to do this, such as using IPsec with Amazon's VPC.
By using Monterey Custom Provisioning Actions, a newly provisioned machine can be configured prior to starting the Monterey network node.
This section gives an example of how to configure an OpenVPN, where a VPN server is running in a private data center behind a firewall. This code and configuration should be used as a guide only for setting up a VPN.
The NodeProvisioningListener code, shown below, copies the configuration files and script for setting up the VPN:
public class VpnProvisioningListener implements NodeProvisioningListener {
private static final Logger LOG = Logger.getLogger(VpnProvisioningListener.class.getName());
private final List<String> providers = Arrays.asList("aws-ec2","gogrid");
@Override
public void postCreateHost(Host host, MontereyLocation location) {
final String provider = location.getProvider();
if (!providers.contains(provider)) {
LOG.info("Skipping VPN listener: host:"+host+"; provider:"+provider);
return;
}
try {
LOG.info("VPN setup: host:"+host+"; provider:"+provider);
final String vpnDir = "/my/path/vpn";
host.executeSsh(Arrays.asList("mkdir -p /etc/openvpn"));
host.copyFileToHost(new File(vpnDir+"/openvpn-bounce-key"), "/etc/openvpn/bounce-key");
executeSshFailFast(host, Arrays.asList("chmod 0600 /etc/openvpn/bounce-key"));
host.copyFileToHost(new File(vpnDir+"/openvpn-foo.crt"), "/etc/openvpn/foo.crt");
host.copyFileToHost(new File(vpnDir+"/openvpn-foo.key"), "/etc/openvpn/foo.key");
host.copyFileToHost(new File(vpnDir+"/openvpn-ca.crt"), "/etc/openvpn/ca.crt");
host.copyFileToHost(new File(vpnDir+"/openvpn-client.conf"), "/etc/openvpn/client.conf");
host.copyFileToHost(new File(vpnDir+"/openvpn-bootstrap.sh"), "/etc/openvpn/bootstrap.sh");
executeSshFailFast(host, Arrays.asList("sh /etc/openvpn/bootstrap.sh"));
} catch (IOException e) {
LOG.log(Level.WARNING,"Error updating VPN",e);
return;
}
}
private void executeSshFailFast(Host host, List<String> cmds) throws IOException {
RemoteExecutionResult result = host.executeSsh(cmds);
if (result.getExitValue() != 0) {
throw new IllegalStateException("Error executing cmd="+cmds+"; exitCode="+result.getExitValue()+"; stderr="+result.getStderr()+"; stdout="+result.getStdout());
}
}
}
The openvpn-client.conf is shown below:
client dev tun proto tcp remote localhost 1194 resolv-retry infinite nobind persist-key persist-tun ca ca.crt cert "foo.crt" key "foo.key" ns-cert-type server comp-lzo verb 3
The openvpn-bootstrap.sh is shown below. This installs openVPN, sets up SSH forwarding, and then starts the openVPN:
#!/bin/sh yum install -y openvpn nohup ssh -Nf -L1194:123.123.123.123:1194 -o StrictHostKeyChecking=no -o CheckHostIP=no -i /etc/openvpn/bounce-key vpnbounce@server1.example.com >/dev/null 2>/dev/null </dev/null service openvpn start
Cloudsoft is always eager to receive customer feedback. We have scores of ideas for functionality that could be added. We recognise there are many applications which don't fit the current API. However the underlying technology for application mobility is capable of much more sophisticated application configurations, expanding the class of applications that could be hosted on the Monterey platform. The main challenge is determining how to extend the API for hosting applications without making it overly complicated. And the main obstacle is time: your input will help us prioritize the capabilities and shape future APIs to make Monterey the broadest and best platform for elasticity.
Some of the limitations you might come across are addressed by features that we're actively exploring. These are summarised below.
Different segments cannot easily share information with each other
The MediationSegmentService implementations can connect to any data storage platform (e.g. CloudDB, SimpleDB, Oracle), but there are cases where it would be useful to have inter-mediator communication offered by Monterey Middleware. This could be used for shared data storage and much more. Research is ongoing into a generalized Monterey network architecture which enables this while preserving the application mobility and exactly-once in-order delivery requirements.
The policies don't do what I want
We have provided several illustrative policies. Some customers entering production will require substantially more sophisticated policies taking in to account value and QoS constraints per segment and per client, as well as integration with provisioning and management systems in place. Customers are free to implement their own policies using the user policy API, however, we recommend you get assistance from Cloudsoft Professional Services for non-trivial policies.
This version is missing the features I really want
Let us know the feature and use-case, and we will see about adding it into a future release.
My enterprise has special security requirements, etc.
Cloudsoft Professional Services can help you configure Monterey Middleware and can perform customizations for different environments. Please contact us to discuss further.
Our biggest driver in choosing among these, and shaping our APIs, is the applications that our users are building. Please let us know what you're building, and if you're interested in finding out more -- or if you have requests for new features -- contact us at support@cloudsoftcorp.com or through our website, http://www.cloudsoftcorp.com/.
A reference application, EZ-Brokerage, is provided to showcase the features of the Monterey platform. This is a distributed stock exchange, incorporating stock handlers that implement the matching algorithm for each instrument in the exchange, distributed among the available Monterey Mediator nodes, and client gateways that are hosted at the Monterey LPP nodes and present an HTTP interface to remote client applications (typically running on traders' workstations).
The internal implementation of the application is descibed in more detail in the tutorial "Porting a Legacy Application to the Monterey Platform: EZ-Brokerage", accessible from within the Monterey Studio.
The application contributes a custom view to the Eclipse workbench, which shows typical trading data about each of the instruments in the exchange, as well as their current order books of unsatisfied "buy" and "sell" orders.
Selecting a stock from the table on the left will cause its order book to be displayed in the right-hand pane. The order book updates in real-time as orders are placed by connected users (or by programmatic bots for testing or simulation).
Each of the EZ-Brokerage client gateways (hosted at the Monterey LPP nodes) starts an embedded web-server, which allows client applications (e.g. the trader view) to retrieve the public state of the order books of all the instruments in the exchange. The client can connect via any of the available LPP nodes; they are all equivalent.
If the view is not connected to any gateway (for instance, if no LPP nodes have been rolled-out in the network, or if the Disconnect action was performed), the view will appear in the disconnected state:
Which client gateway is being used can be specified via the Connect via Gateway menu, accessible from the view menu. If the Automatically Connect option is checked, the view will connect to the first gateway that it discovers at runtime; the connection can be subsequently changed through the Connect via Gateway menu. The Disconnect menu item is disabled whenever this option is selected.