Part 1 of this tutorial we concluded with an web application that displays all our instances and their status. In this part we will add some more features to control our instances.
Prerequisites:
- The project and environment from part 1
Tutorial (complete sourcecode at the end):
- Display the region endpoints and allow to select different one
We hardcoded our endpoint in the first version, if you run instances across the globe in the various AWS datacentres (US, Ireland, Singapore, Tokyo) we need to switch the endpoint easily.
Lets add one more listbox, that we hide in a ZK popup (we could use a combo listbox, but for the sake of playing with all the available ZK components I use the popup). Same concept add a listbox in the zul and a EC2 region list and a list model with customer renderer in our controller. - Start and Stop function for the selected instance
We use the startInstances and stopInstances provided by the Amazon SDK, these functions expect a list of ID’s.
Add 2 additional buttons and related controller functionsNote, these are async calls, we wont know how long it takes to perform the startup or shutdown, so we just throw the result message (JSON which needs to be beautified) as status at the user and ask him to refresh after a while.
- Run the application
Remarks:
- The application is very basic, we still have the access keys hardcoded and no security like a login to protect this web application is in place. I recommend to implement this if you plan to use this on the public web
- There is still some features to be added and improved, we will cover this in part 3.
Complete sourcecode:
instances.zul
<?xml version="1.0" encoding="UTF-8"?>
<zk xmlns="http://www.zkoss.org/2005/zul">
<window id="list" apply="controller.instancesController" title="ZK EC2 CloudControl" width="100%">
<listbox id="lstInstance" width="100%" >
<listhead sizable="true">
<listheader label="Instance ID"/>
<listheader label="Name"/>
<listheader label="Public IP" />
<listheader label="State" />
<listheader label="Launch Time" />
</listhead>
</listbox>
<vbox>
<hbox>
<label value="Selected Endpoint:" />
<label id="lblEndpoint"/>
</hbox>
<button id="btnRefresh" label="Refresh" />
<hbox>
<button id="btnStart" label="Start instance" />
<button id="btnStop" label="Stop instance" />
<label id="lblStatus"/>
</hbox>
<button id="btnEndPoints" label="Show endpoints" onClick='regions.open(list,"overlap")'/>
</vbox>
<popup id="regions" width="350px" >
<listbox id="lstRegion" width="100%">
<listhead sizable="true" >
<listheader id="a" label="Region Name"/>
<listheader id="b" label="Region Endpoint" />
</listhead>
</listbox>
<button id="btnSelectEndpoint" label="Select Endpoint" onClick=""/>
<button id="btnCloseEndPoints" label="Close" onClick='regions.close()'/>
</popup>
</window>
</zk>
instancesController.java
package controller;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.ec2.AmazonEC2;
import com.amazonaws.services.ec2.AmazonEC2Client;
import com.amazonaws.services.ec2.model.DescribeInstancesResult;
import com.amazonaws.services.ec2.model.DescribeRegionsResult;
import com.amazonaws.services.ec2.model.Instance;
import com.amazonaws.services.ec2.model.InstanceState;
import com.amazonaws.services.ec2.model.Region;
import com.amazonaws.services.ec2.model.Reservation;
import com.amazonaws.services.ec2.model.StartInstancesRequest;
import com.amazonaws.services.ec2.model.StartInstancesResult;
import com.amazonaws.services.ec2.model.StopInstancesRequest;
import com.amazonaws.services.ec2.model.StopInstancesResult;
import com.amazonaws.services.ec2.model.Tag;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.util.ComposerExt;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Label;
import org.zkoss.zul.ListModelList;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listcell;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.ListitemRenderer;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Popup;
public class instancesController extends GenericForwardComposer implements ComposerExt {
// ZK Variables
private Listbox lstInstance;
private Listbox lstRegion;
private Label lblStatus;
private Label lblEndpoint;
private Popup regions;
//Amazon Variables
AmazonEC2 ec2;
List<Reservation> listEC2Reservations = null;
List<Instance> listEC2Instances = null;
List<Region> listEC2Regions = null;
String msgboxTitle = "ZKEC2CloudControl";
String defEndpoint = "ec2.ap-southeast-1.amazonaws.com";
private void initEC2() {
BasicAWSCredentials ecProp = new BasicAWSCredentials("{YOURKEY}", "{YOURSCRETKEY});
ec2 = new AmazonEC2Client(ecProp);
ec2.setEndpoint(defEndpoint);
}
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
initEC2();
setupRenderer();
lblEndpoint.setValue(defEndpoint);
listReservationsInstances();
// Retrieve the available EC2 regions
DescribeRegionsResult regionsResult = ec2.describeRegions();
listEC2Regions = regionsResult.getRegions();
lstRegion.setModel(new ListModelList(listEC2Regions));
}
private void listReservationsInstances() {
DescribeInstancesResult describeInstancesRequest = ec2.describeInstances();
listEC2Reservations = describeInstancesRequest.getReservations();
Set<Instance> instances = new HashSet<Instance>();
for (Reservation reservation : listEC2Reservations) {
instances.addAll(reservation.getInstances());
}
listEC2Instances = new ArrayList<Instance>(instances);
lstInstance.setModel(new ListModelList(listEC2Instances));
}
public void onClick$btnRefresh(Event evt) throws InterruptedException {
listReservationsInstances();
lblStatus.setValue("");
}
public void onClick$btnSelectEndpoint(Event evt) throws InterruptedException {
if (lstRegion.getSelectedIndex() > -1) {
String newEndpoint = ((Region)lstRegion.getSelectedItem().getValue()).getEndpoint();
ec2.setEndpoint(newEndpoint);
lblEndpoint.setValue(newEndpoint);
listReservationsInstances();
regions.close();
}
}
public void onClick$btnStart(Event evt) throws InterruptedException {
if (lstInstance.getSelectedIndex() > -1) {
if (Messagebox.show("Start instance <" + ((Instance) lstInstance.getSelectedItem().getValue()).getInstanceId() + "> ?", msgboxTitle, Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION, null) == Messagebox.OK) {
List<String> startIDs = new ArrayList<String>();
startIDs.add(((Instance) lstInstance.getSelectedItem().getValue()).getInstanceId());
StartInstancesRequest start = new StartInstancesRequest(startIDs);
StartInstancesResult result = ec2.startInstances(start);
lblStatus.setValue(result.toString() + " Refresh after 10 or more seconds.");
}
}
}
public void onClick$btnStop(Event evt) throws InterruptedException {
if (lstInstance.getSelectedIndex() > -1) {
if (Messagebox.show("Stop instance <" + ((Instance) lstInstance.getSelectedItem().getValue()).getInstanceId() + "> ?", msgboxTitle, Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION, null) == Messagebox.OK) {
List<String> stopIDs = new ArrayList<String>();
stopIDs.add(((Instance) lstInstance.getSelectedItem().getValue()).getInstanceId());
StopInstancesRequest stop = new StopInstancesRequest(stopIDs);
StopInstancesResult result = ec2.stopInstances(stop);
lblStatus.setValue(result.toString() + " Refresh after 10 or more seconds.");
}
}
}
private void setupRenderer() {
// EC2 Instances list renderer
ListitemRenderer listRenderInstance = new ListitemRenderer() {
@Override
public void render(Listitem item, Object data) throws Exception {
item.setValue(data);
item.appendChild(new Listcell(((Instance) data).getInstanceId()));
item.appendChild(new Listcell(findTagValuebyKey(((Instance) data).getTags(), "name")));
item.appendChild(new Listcell(((Instance) data).getPublicIpAddress()));
InstanceState state = ((Instance) data).getState();
item.appendChild(new Listcell(state.getName()));
item.appendChild(new Listcell(((Instance) data).getLaunchTime().toString()));
Listcell listcell = new Listcell();
item.appendChild(listcell);
}
};
lstInstance.setItemRenderer(listRenderInstance);
// EC2 Regions list renderer
ListitemRenderer listitem = new ListitemRenderer() {
@Override
public void render(Listitem item, Object data) throws Exception {
item.setValue(data);
item.appendChild(new Listcell(((Region) data).getRegionName()));
item.appendChild(new Listcell(((Region) data).getEndpoint()));
Listcell listcell = new Listcell();
item.appendChild(listcell);
}
};
lstRegion.setItemRenderer(listitem);
}
private String findTagValuebyKey(List<Tag> tags, String key) {
for (Tag tag : tags) {
if (tag.getKey().toUpperCase().equals(key.toUpperCase())) {
return tag.getValue();
}
}
return "na";
}
}
Advertisement






[...] The project from part 1 and 2 (link) [...]
Pingback by ZK goes EC2 (Part 3) « The JavaDude Weblog — November 25, 2011 @ 9:44 pm |