You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by bf...@apache.org on 2012/06/28 19:55:23 UTC

[2/2] git commit: Add base VPC UI

Add base VPC UI

** Note: this is a work-in-progress, and only contains dummy content

Implement UI for managing VPC tiers, via a custom chart-like UI list
tiers and allowing the management of VMs associated with the VPCs.


Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/c347c6bd
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/c347c6bd
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/c347c6bd

Branch: refs/heads/master
Commit: c347c6bd095efa37387d5026124b85297a4dea07
Parents: e6a6f84
Author: Brian Federle <br...@citrix.com>
Authored: Thu Jun 28 10:49:25 2012 -0700
Committer: Brian Federle <br...@citrix.com>
Committed: Thu Jun 28 10:51:56 2012 -0700

----------------------------------------------------------------------
 ui/css/cloudstack3.css                 |  352 ++++++++++++++++++-
 ui/images/bg-gradients.png             |  Bin 8322 -> 7539 bytes
 ui/index.jsp                           |    3 +
 ui/scripts/instanceWizard.js           |  513 +++++++++++++++++++++++++++
 ui/scripts/instances.js                |  513 +--------------------------
 ui/scripts/network.js                  |   87 +++++-
 ui/scripts/ui-custom/instanceWizard.js |    2 +-
 ui/scripts/ui-custom/vpc.js            |  404 +++++++++++++++++++++
 ui/scripts/vpc.js                      |  469 ++++++++++++++++++++++++
 9 files changed, 1825 insertions(+), 518 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c347c6bd/ui/css/cloudstack3.css
----------------------------------------------------------------------
diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css
index 573afe9..7fbc366 100644
--- a/ui/css/cloudstack3.css
+++ b/ui/css/cloudstack3.css
@@ -8837,6 +8837,346 @@ div.panel.ui-dialog div.list-view div.fixed-header {
   background: #DFE1E3;
 }
 
+/*VPC / vApps*/
+.vpc-chart {
+  width: 100%;
+  height: 93%;
+  overflow: auto;
+  position: relative;
+  margin: 30px 0 0;
+}
+
+.vpc-chart .vpc-title {
+  font-size: 24px;
+  /*+placement:shift 50px 40px;*/
+  position: relative;
+  left: 50px;
+  top: 40px;
+  position: absolute;
+  color: #5F768A;
+}
+
+.vpc-chart ul.tiers {
+  padding: 0 0 0 26px;
+  margin: 79px 0 0 232px;
+  border-left: 3px solid #CCC;
+}
+
+.vpc-chart li.tier {
+  display: block;
+  width: 258px;
+  height: 107px;
+  margin: -55px 0 90px;
+  /*+border-radius:4px;*/
+  -moz-border-radius: 4px;
+  -webkit-border-radius: 4px;
+  -khtml-border-radius: 4px;
+  border-radius: 4px;
+  border: 1px solid #50545A;
+  background: url(../images/bg-gradients.png) 0px -2637px;
+  /*+placement:shift 0px 58px;*/
+  position: relative;
+  left: 0px;
+  top: 58px;
+  position: relative;
+  /*+box-shadow:0px 5px 7px #DADADA;*/
+  -moz-box-shadow: 0px 5px 7px #DADADA;
+  -webkit-box-shadow: 0px 5px 7px #DADADA;
+  -o-box-shadow: 0px 5px 7px #DADADA;
+  box-shadow: 0px 5px 7px #DADADA;
+}
+
+.vpc-chart li.tier .loading-overlay {
+  /*+border-radius:4px;*/
+  -moz-border-radius: 4px;
+  -webkit-border-radius: 4px;
+  -khtml-border-radius: 4px;
+  border-radius: 4px;
+}
+
+.vpc-chart li.tier .connect-line {
+  position: absolute;
+  width: 28px;
+  height: 3px;
+  background: #CCCCCC 0px -8px;
+  /*+placement:shift -29px 49px;*/
+  position: relative;
+  left: -29px;
+  top: 49px;
+  position: absolute;
+}
+
+.vpc-chart li.tier span.title {
+  color: #FFFFFF;
+  /*+placement:shift 11px 13px;*/
+  position: relative;
+  left: 11px;
+  top: 13px;
+  position: absolute;
+  font-size: 24px;
+  /*+text-shadow:1px 2px 2px #000000;*/
+  -moz-text-shadow: 1px 2px 2px #000000;
+  -webkit-text-shadow: 1px 2px 2px #000000;
+  -o-text-shadow: 1px 2px 2px #000000;
+  text-shadow: 1px 2px 2px #000000;
+}
+
+.vpc-chart li.tier span.cidr {
+  /*+placement:shift 12px 46px;*/
+  position: relative;
+  left: 12px;
+  top: 46px;
+  position: absolute;
+  font-size: 14px;
+  /*+text-shadow:0px -1px 1px #343E4C;*/
+  -moz-text-shadow: 0px -1px 1px #343E4C;
+  -webkit-text-shadow: 0px -1px 1px #343E4C;
+  -o-text-shadow: 0px -1px 1px #343E4C;
+  text-shadow: 0px -1px 1px #343E4C;
+  color: #FFFFFF;
+}
+
+.vpc-chart li.tier .actions {
+  width: 258px;
+  height: 35px;
+  background: #CCC;
+  /*+border-radius:0 0 4px 4px;*/
+  -moz-border-radius: 0 0 4px 4px;
+  -webkit-border-radius: 0 0 4px 4px;
+  -khtml-border-radius: 0 0 4px 4px;
+  border-radius: 0 0 4px 4px;
+  /*+placement:shift -1px 71px;*/
+  position: relative;
+  left: -1px;
+  top: 71px;
+  position: absolute;
+  /*+box-shadow:inset 0px 1px #FFFFFF;*/
+  -moz-box-shadow: inset 0px 1px #FFFFFF;
+  -webkit-box-shadow: inset 0px 1px #FFFFFF;
+  -o-box-shadow: inset 0px 1px #FFFFFF;
+  box-shadow: inset 0px 1px #FFFFFF;
+  border: 1px solid #808080;
+  border-top: 1px solid #4C545E;
+  position: absolute;
+}
+
+.vpc-chart li.tier .actions .action {
+  cursor: pointer;
+  float: left;
+  width: 50px;
+  height: 24px;
+  text-align: center;
+  /*+border-radius:4px;*/
+  -moz-border-radius: 4px;
+  -webkit-border-radius: 4px;
+  -khtml-border-radius: 4px;
+  border-radius: 4px;
+  margin: 4px 0px 4px 4px;
+  border: 1px solid #909090;
+  color: #4B637A;
+  font-weight: bold;
+  /*+text-shadow:0px 1px 1px #FFFFFF;*/
+  -moz-text-shadow: 0px 1px 1px #FFFFFF;
+  -webkit-text-shadow: 0px 1px 1px #FFFFFF;
+  -o-text-shadow: 0px 1px 1px #FFFFFF;
+  text-shadow: 0px 1px 1px #FFFFFF;
+  background: url(../images/bg-gradients.png) 0px -2533px;
+}
+
+.vpc-chart li.tier .actions .action.disabled,
+.vpc-chart li.tier .actions .action.disabled:hover {
+  color: #9D9D9D;
+  background: #CFCFCF;
+  /*+text-shadow:none;*/
+  -moz-text-shadow: none;
+  -webkit-text-shadow: none;
+  -o-text-shadow: none;
+  text-shadow: none;
+  border-color: #B5B5B5;
+  cursor: not-allowed;
+  /*+box-shadow:none;*/
+  -moz-box-shadow: none;
+  -webkit-box-shadow: none;
+  -o-box-shadow: none;
+  box-shadow: none;
+}
+
+.vpc-chart li.tier .actions .action:hover {
+  border: 1px solid #7A8B9A;
+  background-position: 0px -106px;
+  color: #5B7A96;
+  /*+box-shadow:inset 1px 2px 4px #808080;*/
+  -moz-box-shadow: inset 1px 2px 4px #808080;
+  -webkit-box-shadow: inset 1px 2px 4px #808080;
+  -o-box-shadow: inset 1px 2px 4px #808080;
+  box-shadow: inset 1px 2px 4px #808080;
+}
+
+.vpc-chart li.tier .actions .action span.label {
+  /*+placement:shift 1px 3px;*/
+  position: relative;
+  left: 1px;
+  top: 3px;
+  font-size: 11px;
+}
+
+.vpc-chart li.tier .actions .action.remove,
+.vpc-chart li.tier .actions .action.remove:hover {
+  background: none;
+  width: 30px;
+  padding: 0;
+  float: right;
+  border: none;
+  /*+placement:shift -3px -2px;*/
+  position: relative;
+  left: -3px;
+  top: -2px;
+  /*+box-shadow:none;*/
+  -moz-box-shadow: none;
+  -webkit-box-shadow: none;
+  -o-box-shadow: none;
+  box-shadow: none;
+}
+
+.vpc-chart li.tier .action span.icon {
+  background-image: url(../images/sprites.png);
+  cursor: pointer;
+  width: 37px;
+  height: 23px;
+  float: left;
+  /*+placement:shift 1px 3px;*/
+  position: relative;
+  left: 1px;
+  top: 3px;
+}
+
+.vpc-chart li.tier .vm-count {
+  font-size: 23px;
+  left: 134px;
+  top: 3px;
+  position: absolute;
+  color: #FFFFFF;
+  /*+text-shadow:1px 2px 2px #000000;*/
+  -moz-text-shadow: 1px 2px 2px #000000;
+  -webkit-text-shadow: 1px 2px 2px #000000;
+  -o-text-shadow: 1px 2px 2px #000000;
+  text-shadow: 1px 2px 2px #000000;
+  cursor: pointer;
+  display: block;
+  padding: 5px;
+  text-align: center;
+  width: 100px;
+  border: 1px solid transparent;
+  margin: 4px;
+}
+
+.vpc-chart li.tier .vm-count:hover {
+  border-radius: 4px;
+  border: 1px solid #4C545E;
+  background: url(../images/bg-gradients.png) 0px -2751px;
+}
+
+.vpc-chart li.tier .vm-count .total {
+  padding-right: 4px;
+  font-size: 24px;
+}
+
+.vpc-chart li.tier.placeholder {
+  background: #ECECEC;
+  border: dotted #ACACAC;
+  /*+border-radius:4px;*/
+  -moz-border-radius: 4px;
+  -webkit-border-radius: 4px;
+  -khtml-border-radius: 4px;
+  border-radius: 4px;
+  /*+box-shadow:none;*/
+  -moz-box-shadow: none;
+  -webkit-box-shadow: none;
+  -o-box-shadow: none;
+  box-shadow: none;
+  cursor: pointer;
+}
+
+.vpc-chart li.tier.placeholder:hover {
+  background: #D3D3D3;
+  /*+box-shadow:0px 2px 8px #A7A7A7;*/
+  -moz-box-shadow: 0px 2px 8px #A7A7A7;
+  -webkit-box-shadow: 0px 2px 8px #A7A7A7;
+  -o-box-shadow: 0px 2px 8px #A7A7A7;
+  box-shadow: 0px 2px 8px #A7A7A7;
+}
+
+.vpc-chart li.tier.placeholder span {
+  top: 40px;
+  left: 66px;
+  color: #9F9F9F;
+  /*+text-shadow:none;*/
+  -moz-text-shadow: none;
+  -webkit-text-shadow: none;
+  -o-text-shadow: none;
+  text-shadow: none;
+}
+
+.vpc-chart li.tier.placeholder:hover span {
+  color: #000000;
+  /*+text-shadow:0px 0px 7px #FFFFFF;*/
+  -moz-text-shadow: 0px 0px 7px #FFFFFF;
+  -webkit-text-shadow: 0px 0px 7px #FFFFFF;
+  -o-text-shadow: 0px 0px 7px #FFFFFF;
+  text-shadow: 0px 0px 7px #FFFFFF;
+}
+
+.vpc-chart li.tier.virtual-router {
+  margin: 0px;
+  width: 222px;
+  height: 65px;
+  /*+placement:shift 17px -36px;*/
+  position: relative;
+  left: 17px;
+  top: -36px;
+  background-position: 0px -2519px;
+  border: 1px solid #ADADAD;
+}
+
+.vpc-chart li.tier.virtual-router span {
+  color: #586E82;
+  font-size: 18px;
+  /*+text-shadow:0px 1px 3px #FFFFFF;*/
+  -moz-text-shadow: 0px 1px 3px #FFFFFF;
+  -webkit-text-shadow: 0px 1px 3px #FFFFFF;
+  -o-text-shadow: 0px 1px 3px #FFFFFF;
+  text-shadow: 0px 1px 3px #FFFFFF;
+  /*+placement:shift 53px 22px;*/
+  position: relative;
+  left: 53px;
+  top: 22px;
+}
+
+.vpc-chart li.tier.virtual-router .connect-line {
+  /*+placement:shift -47px 14px;*/
+  position: relative;
+  left: -47px;
+  top: 14px;
+  width: 46px;
+}
+
+/*Configure ACL dialog*/
+.ui-dialog.configure-acl {
+}
+
+.ui-dialog.configure-acl .ui-dialog-buttonpane {
+  /*+placement:shift 709px -2px;*/
+  position: relative;
+  left: 709px;
+  top: -2px;
+}
+
+.ui-dialog.configure-acl .multi-edit .data {
+  width: 807px;
+  height: 370px;
+  overflow: auto;
+}
+
 /*Action icons*/
 .action.edit .icon {
   background-position: 1px -1px;
@@ -9005,13 +9345,15 @@ div.panel.ui-dialog div.list-view div.fixed-header {
 
 .create .icon,
 .createTemplate .icon,
-.enableSwift .icon {
+.enableSwift .icon,
+.addVM .icon {
   background-position: -69px -63px;
 }
 
 .create:hover .icon,
 .createTemplate:hover .icon,
-.enableSwift:hover .icon {
+.enableSwift:hover .icon,
+.addVM:hover .icon {
   background-position: -69px -645px;
 }
 
@@ -9073,11 +9415,13 @@ div.panel.ui-dialog div.list-view div.fixed-header {
   background-position: -167px -648px;
 }
 
-.generateKeys .icon {
+.generateKeys .icon,
+.networkACL .icon {
   background-position: -167px -95px;
 }
 
-.generateKeys:hover .icon {
+.generateKeys:hover .icon,
+.networkACL:hover .icon {
   background-position: -167px -677px;
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c347c6bd/ui/images/bg-gradients.png
----------------------------------------------------------------------
diff --git a/ui/images/bg-gradients.png b/ui/images/bg-gradients.png
index 2ef7454..52016f0 100644
Binary files a/ui/images/bg-gradients.png and b/ui/images/bg-gradients.png differ

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c347c6bd/ui/index.jsp
----------------------------------------------------------------------
diff --git a/ui/index.jsp b/ui/index.jsp
index 3c377ea..fb3327f 100644
--- a/ui/index.jsp
+++ b/ui/index.jsp
@@ -1629,11 +1629,14 @@
     <script type="text/javascript" src="scripts/projects.js?t=<%=now%>"></script>
     <script type="text/javascript" src="scripts/dashboard.js?t=<%=now%>"></script>
     <script type="text/javascript" src="scripts/ui-custom/instanceWizard.js?t=<%=now%>"></script>
+    <script type="text/javascript" src="scripts/instanceWizard.js?t=<%=now%>"></script>
     <script type="text/javascript" src="scripts/instances.js?t=<%=now%>"></script>
     <script type="text/javascript" src="scripts/events.js?t=<%=now%>"></script>
     <script type="text/javascript" src="scripts/ui-custom/ipRules.js?t=<%=now%>"></script>
     <script type="text/javascript" src="scripts/ui-custom/enableStaticNAT.js?t=<%=now%>"></script>
     <script type="text/javascript" src="scripts/ui-custom/securityRules.js?t=<%=now%>"></script>
+    <script type="text/javascript" src="scripts/ui-custom/vpc.js?t=<%=now%>"></script>
+    <script type="text/javascript" src="scripts/vpc.js?t=<%=now%>"></script>
     <script type="text/javascript" src="scripts/network.js?t=<%=now%>"></script>
     <script type="text/javascript" src="scripts/ui-custom/recurringSnapshots.js?t=<%=now%>"></script>
     <script type="text/javascript" src="scripts/ui-custom/uploadVolume.js?t=<%=now%>"></script>

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c347c6bd/ui/scripts/instanceWizard.js
----------------------------------------------------------------------
diff --git a/ui/scripts/instanceWizard.js b/ui/scripts/instanceWizard.js
new file mode 100644
index 0000000..8559477
--- /dev/null
+++ b/ui/scripts/instanceWizard.js
@@ -0,0 +1,513 @@
+(function($, cloudStack) {
+  var zoneObjs, hypervisorObjs, featuredTemplateObjs, communityTemplateObjs, myTemplateObjs, featuredIsoObjs, community
+  var selectedZoneObj, selectedTemplateObj, selectedHypervisor, selectedDiskOfferingObj; 
+  var step5ContainerType = 'nothing-to-select'; //'nothing-to-select', 'select-network', 'select-security-group'
+
+  cloudStack.instanceWizard = {
+    maxDiskOfferingSize: function() {
+      return g_capabilities.customdiskofferingmaxsize;
+    },
+    steps: [
+      // Step 1: Setup
+      function(args) {
+      $.ajax({
+        url: createURL("listZones&available=true"),
+        dataType: "json",
+        async: false,
+        success: function(json) {
+          zoneObjs = json.listzonesresponse.zone;
+          args.response.success({ data: {zones: zoneObjs}});
+        }
+      });
+    },
+
+    // Step 2: Select template
+    function(args) {
+      $(zoneObjs).each(function(){
+        if(this.id == args.currentData.zoneid) {
+          selectedZoneObj = this;
+          return false; //break the $.each() loop
+        }
+      });
+      if(selectedZoneObj == null) {
+        alert("error: can't find matched zone object");
+        return;
+      }
+
+      $.ajax({
+        url: createURL("listHypervisors&zoneid="+args.currentData.zoneid),
+        dataType: "json",
+        async: false,
+        success: function(json) {
+          hypervisorObjs = json.listhypervisorsresponse.hypervisor;
+        }
+      });
+
+      //***** get templates/ISOs (begin) *****
+      var selectedTemplate = args.currentData['select-template'];
+      if (selectedTemplate == 'select-template') {
+        var hypervisorArray = [];
+        $(hypervisorObjs).each(function(index, item) {									 
+          hypervisorArray.push(item.name);
+        });
+
+        $.ajax({
+          url: createURL("listTemplates&templatefilter=featured&zoneid="+args.currentData.zoneid),
+          dataType: "json",
+          async: false,
+          success: function(json) {										  
+            featuredTemplateObjs = $.grep(json.listtemplatesresponse.template, function(item, index) {											  
+              if($.inArray(item.hypervisor, hypervisorArray) > -1)
+                return true;
+            });	
+          }
+        });
+        $.ajax({
+          url: createURL("listTemplates&templatefilter=community&zoneid="+args.currentData.zoneid),
+          dataType: "json",
+          async: false,
+          success: function(json) {
+            communityTemplateObjs = $.grep(json.listtemplatesresponse.template, function(item, index) {											  
+              if($.inArray(item.hypervisor, hypervisorArray) > -1)
+                return true;
+            });	
+          }
+        });
+        $.ajax({
+          url: createURL("listTemplates&templatefilter=selfexecutable&zoneid="+args.currentData.zoneid),
+          dataType: "json",
+          async: false,
+          success: function(json) {
+            myTemplateObjs = $.grep(json.listtemplatesresponse.template, function(item, index) {											  
+              if($.inArray(item.hypervisor, hypervisorArray) > -1)
+                return true;
+            });	
+          }
+        });
+      } else if (selectedTemplate == 'select-iso') {
+        $.ajax({
+          url: createURL("listIsos&isofilter=featured&zoneid=" + args.currentData.zoneid + "&bootable=true"),
+          dataType: "json",
+          async: false,
+          success: function(json) {
+            featuredIsoObjs = json.listisosresponse.iso;
+          }
+        });
+        $.ajax({
+          url: createURL("listIsos&isofilter=community&zoneid=" + args.currentData.zoneid + "&bootable=true"),
+          dataType: "json",
+          async: false,
+          success: function(json) {
+            communityIsoObjs = json.listisosresponse.iso;
+          }
+        });
+        $.ajax({
+          url: createURL("listIsos&isofilter=selfexecutable&zoneid=" + args.currentData.zoneid + "&bootable=true"),
+          dataType: "json",
+          async: false,
+          success: function(json) {
+            myIsoObjs = json.listisosresponse.iso;
+          }
+        });
+      }
+      //***** get templates/ISOs (end) *****
+
+
+      var templatesObj = {};
+      if (selectedTemplate == 'select-template') {
+        templatesObj = {
+          featuredtemplates: featuredTemplateObjs,
+          communitytemplates: communityTemplateObjs,
+          mytemplates: myTemplateObjs
+        }
+      } else if (selectedTemplate == 'select-iso') {
+        templatesObj = {
+          featuredisos: featuredIsoObjs,
+          communityisos: communityIsoObjs,
+          myisos: myIsoObjs
+        }
+      }
+      args.response.success({
+        hypervisor: {
+          idField: 'name',
+          nameField: 'name'
+        },
+        data: {
+          templates: templatesObj,
+          hypervisors: hypervisorObjs
+        }
+      });
+    },
+
+    // Step 3: Service offering
+    function(args) {
+      if(args.currentData["select-template"] == "select-template") {
+        if(featuredTemplateObjs != null && featuredTemplateObjs.length > 0) {
+          for(var i=0; i < featuredTemplateObjs.length; i++) {
+            if(featuredTemplateObjs[i].id == args.currentData.templateid) {
+              selectedTemplateObj = featuredTemplateObjs[i];
+              break;
+            }
+          }
+        }
+        if(selectedTemplateObj == null) {
+          if(communityTemplateObjs != null && communityTemplateObjs.length > 0) {
+            for(var i=0; i < communityTemplateObjs.length; i++) {
+              if(communityTemplateObjs[i].id == args.currentData.templateid) {
+                selectedTemplateObj = communityTemplateObjs[i];
+                break;
+              }
+            }
+          }
+        }
+        if(selectedTemplateObj == null) {
+          if(myTemplateObjs != null && myTemplateObjs.length > 0) {
+            for(var i=0; i < myTemplateObjs.length; i++) {
+              if(myTemplateObjs[i].id == args.currentData.templateid) {
+                selectedTemplateObj = myTemplateObjs[i];
+                break;
+              }
+            }
+          }
+        }
+        if(selectedTemplateObj == null)
+          alert("unable to find matched template object");
+        else
+          selectedHypervisor = selectedTemplateObj.hypervisor;
+      }
+      else { //(args.currentData["select-template"] == "select-iso"
+        selectedHypervisor = args.currentData.hypervisorid;
+      }
+
+      $.ajax({
+        url: createURL("listServiceOfferings&issystem=false"),
+        dataType: "json",
+        async: true,
+        success: function(json) {
+          serviceOfferingObjs = json.listserviceofferingsresponse.serviceoffering;
+          args.response.success({
+            data: {serviceOfferings: serviceOfferingObjs}
+          });
+        }
+      });
+    },
+
+    // Step 4: Data disk offering
+    function(args) {
+      var isRequred = (args.currentData["select-template"] == "select-iso"? true: false);
+      $.ajax({
+        url: createURL("listDiskOfferings"),
+        dataType: "json",
+        async: true,
+        success: function(json) {
+          diskOfferingObjs = json.listdiskofferingsresponse.diskoffering;
+          args.response.success({
+            required: isRequred,
+            customFlag: 'iscustomized', // Field determines if custom slider is shown
+            data: {diskOfferings: diskOfferingObjs}
+          });
+        }
+      });
+    },
+
+    // Step 5: Network
+    function(args) {
+      if(diskOfferingObjs != null && diskOfferingObjs.length > 0) {
+        for(var i=0; i < diskOfferingObjs.length; i++) {
+          if(diskOfferingObjs[i].id == args.currentData.diskofferingid) {
+            selectedDiskOfferingObj = diskOfferingObjs[i];
+            break;
+          }
+        }
+      }
+
+      if (selectedZoneObj.networktype == "Advanced") {  //Advanced zone. Show network list.
+        step5ContainerType = 'select-network';
+      }
+      else { //Basic zone. Show securigy group list or nothing(when no SecurityGroup service in guest network)
+        var includingSecurityGroupService = false;
+        $.ajax({
+          url: createURL("listNetworks&trafficType=Guest&zoneId=" + selectedZoneObj.id),
+          dataType: "json",
+          async: false,
+          success: function(json) {
+            //basic zone should have only one guest network returned in this API call
+            var items = json.listnetworksresponse.network;
+            if(items != null && items.length > 0) {
+              var networkObj = items[0];    //basic zone has only one guest network
+              var serviceObjArray = networkObj.service;
+              for(var k = 0; k < serviceObjArray.length; k++) {
+                if(serviceObjArray[k].name == "SecurityGroup") {
+                  includingSecurityGroupService = true;
+                  break;
+                }
+              }
+            }
+          }
+        });
+
+        if(includingSecurityGroupService == false || selectedHypervisor == "VMware") {
+          step5ContainerType = 'nothing-to-select';
+        }
+        else {
+          step5ContainerType = 'select-security-group';
+        }
+      }
+
+      //step5ContainerType = 'nothing-to-select'; //for testing only, comment it out before checking in
+      if(step5ContainerType == 'select-network') {
+        var defaultNetworkArray = [], optionalNetworkArray = [];
+        var networkData = {
+          zoneId: args.currentData.zoneid
+        };
+
+        if (!(cloudStack.context.projects && cloudStack.context.projects[0])) {
+          networkData.domainid = g_domainid;
+          networkData.account = g_account;
+        }
+
+        var networkObjs;
+        $.ajax({
+          url: createURL('listNetworks'),
+          data: networkData,
+          dataType: "json",
+          async: false,
+          success: function(json) {
+            networkObjs = json.listnetworksresponse.network ? json.listnetworksresponse.network : [];
+          }
+        });
+
+
+        var apiCmd = "listNetworkOfferings&guestiptype=Isolated&supportedServices=sourceNat&state=Enabled&specifyvlan=false&zoneid=" + args.currentData.zoneid ; 
+        var array1 = [];
+        var guestTrafficTypeTotal = 0;
+
+        $.ajax({
+          url: createURL(apiCmd + array1.join("")), //get the network offering for isolated network with sourceNat
+          dataType: "json",
+          async: false,
+          success: function(json) {
+            networkOfferingObjs  = json.listnetworkofferingsresponse.networkoffering;
+          }
+        });
+        //get network offerings (end)	***			
+
+
+        args.response.success({
+          type: 'select-network',
+          data: {
+            myNetworks: [], //not used any more
+            sharedNetworks: networkObjs,
+            securityGroups: [],
+            networkOfferings: networkOfferingObjs
+          }
+        });
+      }
+
+      else if(step5ContainerType == 'select-security-group') {
+        var securityGroupArray = [];
+        var data = {
+          domainid: g_domainid,
+          account: g_account
+        };
+
+        $.ajax({
+          url: createURL("listSecurityGroups"),
+          dataType: "json",
+          async: false,
+          data: cloudStack.context.projects ? {} : data,
+          success: function(json) {
+            var items = json.listsecuritygroupsresponse.securitygroup;
+            if (items != null && items.length > 0) {
+              for (var i = 0; i < items.length; i++) {
+                if(items[i].name != "default") //exclude default security group because it is always applied
+                  securityGroupArray.push(items[i]);
+              }
+            }
+          }
+        });
+        args.response.success({
+          type: 'select-security-group',
+          data: {
+            myNetworks: [], //not used any more
+            sharedNetworks: [],
+            securityGroups: securityGroupArray,
+            networkOfferings: []
+          }
+        });
+      }
+
+      else if(step5ContainerType == 'nothing-to-select') {
+        args.response.success({
+          type: 'nothing-to-select',
+          data: {
+            myNetworks: [], //not used any more
+            sharedNetworks: [],
+            securityGroups: [],
+            networkOfferings: []
+          }
+        });
+      }
+
+    },
+
+    // Step 6: Review
+    function(args) {
+      return false;
+    }
+    ],
+    action: function(args) {
+/*
+var isValid = true;
+isValid &= validateString("Name", $thisPopup.find("#wizard_vm_name"), $thisPopup.find("#wizard_vm_name_errormsg"), true);   //optional
+isValid &= validateString("Group", $thisPopup.find("#wizard_vm_group"), $thisPopup.find("#wizard_vm_group_errormsg"), true); //optional
+if (!isValid)
+return;
+*/
+
+      // Create a new VM!!!!
+      var array1 = [];
+
+      //step 1 : select zone
+      array1.push("&zoneId=" + args.data.zoneid);
+
+      //step 2: select template
+      array1.push("&templateId=" + args.data.templateid);
+      array1.push("&hypervisor=" + selectedHypervisor);
+
+      //step 3: select service offering
+      array1.push("&serviceOfferingId=" + args.data.serviceofferingid);
+
+      //step 4: select disk offering
+      if(args.data.diskofferingid != null && args.data.diskofferingid != "0") {
+        array1.push("&diskOfferingId=" + args.data.diskofferingid);
+        if(selectedDiskOfferingObj.iscustomized == true)
+          array1.push("&size=" + args.data.size);
+      }
+
+      //step 5: select network
+      if (step5ContainerType == 'select-network') {
+        var array2 = [];
+        var defaultNetworkId = args.data.defaultNetwork; //args.data.defaultNetwork might be equal to string "new-network" or a network ID
+
+        var checkedNetworkIdArray;
+        if(typeof(args.data["my-networks"]) == "object" && args.data["my-networks"].length != null) { //args.data["my-networks"] is an array of string, e.g. ["203", "202"],
+          checkedNetworkIdArray = args.data["my-networks"];
+        }
+        else if(typeof(args.data["my-networks"]) == "string" && args.data["my-networks"].length > 0) { //args.data["my-networks"] is a string, e.g. "202"
+          checkedNetworkIdArray = [];
+          checkedNetworkIdArray.push(args.data["my-networks"]);
+        }
+        else { // typeof(args.data["my-networks"]) == null
+          checkedNetworkIdArray = [];
+        }
+
+        //create new network starts here
+        if(args.data["new-network"] == "create-new-network") {
+          var isCreateNetworkSuccessful = true;
+          $.ajax({
+            url: createURL("createNetwork&networkOfferingId="+args.data["new-network-networkofferingid"]+"&name="+todb(args.data["new-network-name"])+"&displayText="+todb(args.data["new-network-name"])+"&zoneId="+selectedZoneObj.id),
+            dataType: "json",
+            async: false,
+            success: function(json) {
+              newNetwork = json.createnetworkresponse.network;
+              checkedNetworkIdArray.push(newNetwork.id);
+              if(defaultNetworkId == "new-network")
+                defaultNetworkId = newNetwork.id;
+            },
+            error: function(XMLHttpResponse) {
+              isCreateNetworkSuccessful = false;
+              var errorMsg = "Failed to create new network, unable to proceed to deploy VM. Error: " + parseXMLHttpResponse(XMLHttpResponse);
+              //alert(errorMsg);
+              args.response.error(errorMsg);    //args.response.error(errorMsg) here doesn't show errorMsg. Waiting for Brian to fix it. use alert(errorMsg) to show errorMsg for now.
+            }
+          });
+          if(isCreateNetworkSuccessful == false)
+            return;
+        }
+        //create new network ends here
+
+        //add default network first
+        if(defaultNetworkId != null && defaultNetworkId.length > 0)
+          array2.push(defaultNetworkId);
+
+        //then, add other checked networks
+        if(checkedNetworkIdArray.length > 0) {
+          for(var i=0; i < checkedNetworkIdArray.length; i++) {
+            if(checkedNetworkIdArray[i] != defaultNetworkId) //exclude defaultNetworkId that has been added to array2
+              array2.push(checkedNetworkIdArray[i]);
+          }
+        }
+
+        array1.push("&networkIds=" + array2.join(","));
+      }
+      else if (step5ContainerType == 'select-security-group') {
+        var checkedSecurityGroupIdArray;
+        if(typeof(args.data["security-groups"]) == "object" && args.data["security-groups"].length != null) { //args.data["security-groups"] is an array of string, e.g. ["2375f8cc-8a73-4b8d-9b26-50885a25ffe0", "27c60d2a-de7f-4bb7-96e5-a602cec681df","c6301d77-99b5-4e8a-85e2-3ea2ab31c342"],
+          checkedSecurityGroupIdArray = args.data["security-groups"];
+        }
+        else if(typeof(args.data["security-groups"]) == "string" && args.data["security-groups"].length > 0) { //args.data["security-groups"] is a string, e.g. "2375f8cc-8a73-4b8d-9b26-50885a25ffe0"
+          checkedSecurityGroupIdArray = [];
+          checkedSecurityGroupIdArray.push(args.data["security-groups"]);
+        }
+        else { // typeof(args.data["security-groups"]) == null
+          checkedSecurityGroupIdArray = [];
+        }
+
+        if(checkedSecurityGroupIdArray.length > 0)
+          array1.push("&securitygroupids=" + checkedSecurityGroupIdArray.join(","));
+      }
+
+      var displayname = args.data.displayname;
+      if(displayname != null && displayname.length > 0) {
+        array1.push("&displayname="+todb(displayname));
+        array1.push("&name="+todb(displayname));
+      }
+
+      var group = args.data.groupname;
+      if (group != null && group.length > 0)
+        array1.push("&group="+todb(group));
+
+      //array1.push("&startVm=false");	//for testing only, comment it out before checking in
+
+      $.ajax({
+        url: createURL("deployVirtualMachine"+array1.join("")),
+        dataType: "json",
+        success: function(json) {
+          var jid = json.deployvirtualmachineresponse.jobid;
+          var vmid = json.deployvirtualmachineresponse.id;
+          args.response.success(
+            {_custom:
+              {jobId: jid,
+                getUpdatedItem: function(json) {
+                  var item = json.queryasyncjobresultresponse.jobresult.virtualmachine;
+                  if (item.password != null)
+                    alert("Password of new VM " + item.displayname + " is  " + item.password);
+                  return item;
+                },
+                getActionFilter: function() {
+                  return vmActionfilter;
+                },
+                getUpdatedItemWhenAsyncJobFails: function() {
+                  var item;
+                  $.ajax({
+                    url: createURL("listVirtualMachines&id="+vmid),
+                    dataType: "json",
+                    async: false,
+                    success: function(json) {
+                      item = json.listvirtualmachinesresponse.virtualmachine[0];
+                    }
+                  });
+                  return item;
+                }
+          }
+          }
+          );
+        },
+        error: function(XMLHttpResponse) {
+          args.response.error(parseXMLHttpResponse(XMLHttpResponse)); //wait for Brian to implement
+        }
+      });
+    }
+  };
+}(jQuery, cloudStack));

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c347c6bd/ui/scripts/instances.js
----------------------------------------------------------------------
diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js
index 77688c9..5e9b3f3 100644
--- a/ui/scripts/instances.js
+++ b/ui/scripts/instances.js
@@ -15,11 +15,6 @@
 // specific language governing permissions and limitations
 // under the License.
 (function($, cloudStack) {
-
-  var zoneObjs, hypervisorObjs, featuredTemplateObjs, communityTemplateObjs, myTemplateObjs, featuredIsoObjs, communityIsoObjs, myIsoObjs, serviceOfferingObjs, diskOfferingObjs, networkOfferingObjs, physicalNetworkObjs;
-  var selectedZoneObj, selectedTemplateObj, selectedHypervisor, selectedDiskOfferingObj; 
-  var step5ContainerType = 'nothing-to-select'; //'nothing-to-select', 'select-network', 'select-security-group'
-
   cloudStack.sections.instances = {
     title: 'label.instances',
     id: 'instances',
@@ -69,513 +64,7 @@
           label: 'label.vm.add',
 
           action: {
-            custom: cloudStack.instanceWizard({
-              maxDiskOfferingSize: function() {
-                return g_capabilities.customdiskofferingmaxsize;
-              },
-              steps: [
-                // Step 1: Setup
-                function(args) {
-                  $.ajax({
-                    url: createURL("listZones&available=true"),
-                    dataType: "json",
-                    async: false,
-                    success: function(json) {
-                      zoneObjs = json.listzonesresponse.zone;
-                      args.response.success({ data: {zones: zoneObjs}});
-                    }
-                  });
-                },
-
-                // Step 2: Select template
-                function(args) {
-                  $(zoneObjs).each(function(){
-                    if(this.id == args.currentData.zoneid) {
-                      selectedZoneObj = this;
-                      return false; //break the $.each() loop
-                    }
-                  });
-                  if(selectedZoneObj == null) {
-                    alert("error: can't find matched zone object");
-                    return;
-                  }
-
-                  $.ajax({
-                    url: createURL("listHypervisors&zoneid="+args.currentData.zoneid),
-                    dataType: "json",
-                    async: false,
-                    success: function(json) {
-                      hypervisorObjs = json.listhypervisorsresponse.hypervisor;
-                    }
-                  });
-
-				  //***** get templates/ISOs (begin) *****
-				  var selectedTemplate = args.currentData['select-template'];
-				  if (selectedTemplate == 'select-template') {
-					  var hypervisorArray = [];
-					  $(hypervisorObjs).each(function(index, item) {									 
-							hypervisorArray.push(item.name);
-					  });
-																		
-					  $.ajax({
-						url: createURL("listTemplates&templatefilter=featured&zoneid="+args.currentData.zoneid),
-						dataType: "json",
-						async: false,
-						success: function(json) {										  
-											  featuredTemplateObjs = $.grep(json.listtemplatesresponse.template, function(item, index) {											  
-												  if($.inArray(item.hypervisor, hypervisorArray) > -1)
-													return true;
-												});	
-						}
-					  });
-					  $.ajax({
-						url: createURL("listTemplates&templatefilter=community&zoneid="+args.currentData.zoneid),
-						dataType: "json",
-						async: false,
-						success: function(json) {
-						  communityTemplateObjs = $.grep(json.listtemplatesresponse.template, function(item, index) {											  
-												  if($.inArray(item.hypervisor, hypervisorArray) > -1)
-													return true;
-												});	
-						}
-					  });
-					  $.ajax({
-						url: createURL("listTemplates&templatefilter=selfexecutable&zoneid="+args.currentData.zoneid),
-						dataType: "json",
-						async: false,
-						success: function(json) {
-						  myTemplateObjs = $.grep(json.listtemplatesresponse.template, function(item, index) {											  
-												  if($.inArray(item.hypervisor, hypervisorArray) > -1)
-													return true;
-												});	
-						}
-					  });
-				  } else if (selectedTemplate == 'select-iso') {
-					$.ajax({
-						url: createURL("listIsos&isofilter=featured&zoneid=" + args.currentData.zoneid + "&bootable=true"),
-						dataType: "json",
-						async: false,
-						success: function(json) {
-						  featuredIsoObjs = json.listisosresponse.iso;
-						}
-					});
-					$.ajax({
-						url: createURL("listIsos&isofilter=community&zoneid=" + args.currentData.zoneid + "&bootable=true"),
-						dataType: "json",
-						async: false,
-						success: function(json) {
-						  communityIsoObjs = json.listisosresponse.iso;
-						}
-					});
-					$.ajax({
-						url: createURL("listIsos&isofilter=selfexecutable&zoneid=" + args.currentData.zoneid + "&bootable=true"),
-						dataType: "json",
-						async: false,
-						success: function(json) {
-						  myIsoObjs = json.listisosresponse.iso;
-						}
-					});
-				  }
-				  //***** get templates/ISOs (end) *****
-
-									
-				  var templatesObj = {};
-				  if (selectedTemplate == 'select-template') {
-					templatesObj = {
-						featuredtemplates: featuredTemplateObjs,
-						communitytemplates: communityTemplateObjs,
-						mytemplates: myTemplateObjs
-					}
-				  } else if (selectedTemplate == 'select-iso') {
-					templatesObj = {
-						featuredisos: featuredIsoObjs,
-                        communityisos: communityIsoObjs,
-                        myisos: myIsoObjs
-					}
-				  }
-				  args.response.success({
-                    hypervisor: {
-                      idField: 'name',
-                      nameField: 'name'
-                    },
-                    data: {
-                      templates: templatesObj,
-                      hypervisors: hypervisorObjs
-                    }
-                  });
-                },
-
-                // Step 3: Service offering
-                function(args) {
-                  if(args.currentData["select-template"] == "select-template") {
-                    if(featuredTemplateObjs != null && featuredTemplateObjs.length > 0) {
-                      for(var i=0; i < featuredTemplateObjs.length; i++) {
-                        if(featuredTemplateObjs[i].id == args.currentData.templateid) {
-                          selectedTemplateObj = featuredTemplateObjs[i];
-                          break;
-                        }
-                      }
-                    }
-                    if(selectedTemplateObj == null) {
-                      if(communityTemplateObjs != null && communityTemplateObjs.length > 0) {
-                        for(var i=0; i < communityTemplateObjs.length; i++) {
-                          if(communityTemplateObjs[i].id == args.currentData.templateid) {
-                            selectedTemplateObj = communityTemplateObjs[i];
-                            break;
-                          }
-                        }
-                      }
-                    }
-                    if(selectedTemplateObj == null) {
-                      if(myTemplateObjs != null && myTemplateObjs.length > 0) {
-                        for(var i=0; i < myTemplateObjs.length; i++) {
-                          if(myTemplateObjs[i].id == args.currentData.templateid) {
-                            selectedTemplateObj = myTemplateObjs[i];
-                            break;
-                          }
-                        }
-                      }
-                    }
-                    if(selectedTemplateObj == null)
-                      alert("unable to find matched template object");
-                    else
-                      selectedHypervisor = selectedTemplateObj.hypervisor;
-                  }
-                  else { //(args.currentData["select-template"] == "select-iso"
-                    selectedHypervisor = args.currentData.hypervisorid;
-                  }
-
-                  $.ajax({
-                    url: createURL("listServiceOfferings&issystem=false"),
-                    dataType: "json",
-                    async: true,
-                    success: function(json) {
-                      serviceOfferingObjs = json.listserviceofferingsresponse.serviceoffering;
-                      args.response.success({
-                        data: {serviceOfferings: serviceOfferingObjs}
-                      });
-                    }
-                  });
-                },
-
-                // Step 4: Data disk offering
-                function(args) {
-                  var isRequred = (args.currentData["select-template"] == "select-iso"? true: false);
-                  $.ajax({
-                    url: createURL("listDiskOfferings"),
-                    dataType: "json",
-                    async: true,
-                    success: function(json) {
-                      diskOfferingObjs = json.listdiskofferingsresponse.diskoffering;
-                      args.response.success({
-                        required: isRequred,
-                        customFlag: 'iscustomized', // Field determines if custom slider is shown
-                        data: {diskOfferings: diskOfferingObjs}
-                      });
-                    }
-                  });
-                },
-
-                // Step 5: Network
-                function(args) {
-                  if(diskOfferingObjs != null && diskOfferingObjs.length > 0) {
-                    for(var i=0; i < diskOfferingObjs.length; i++) {
-                      if(diskOfferingObjs[i].id == args.currentData.diskofferingid) {
-                        selectedDiskOfferingObj = diskOfferingObjs[i];
-                        break;
-                      }
-                    }
-                  }
-
-                  if (selectedZoneObj.networktype == "Advanced") {  //Advanced zone. Show network list.
-                    step5ContainerType = 'select-network';
-                  }
-                  else { //Basic zone. Show securigy group list or nothing(when no SecurityGroup service in guest network)
-                    var includingSecurityGroupService = false;
-                    $.ajax({
-                      url: createURL("listNetworks&trafficType=Guest&zoneId=" + selectedZoneObj.id),
-                      dataType: "json",
-                      async: false,
-                      success: function(json) {
-                        //basic zone should have only one guest network returned in this API call
-                        var items = json.listnetworksresponse.network;
-                        if(items != null && items.length > 0) {
-                          var networkObj = items[0];    //basic zone has only one guest network
-                          var serviceObjArray = networkObj.service;
-                          for(var k = 0; k < serviceObjArray.length; k++) {
-                            if(serviceObjArray[k].name == "SecurityGroup") {
-                              includingSecurityGroupService = true;
-                              break;
-                            }
-                          }
-                        }
-                      }
-                    });
-
-                    if(includingSecurityGroupService == false || selectedHypervisor == "VMware") {
-                      step5ContainerType = 'nothing-to-select';
-                    }
-                    else {
-                      step5ContainerType = 'select-security-group';
-                    }
-                  }
-
-                  //step5ContainerType = 'nothing-to-select'; //for testing only, comment it out before checking in
-                  if(step5ContainerType == 'select-network') {
-                    var defaultNetworkArray = [], optionalNetworkArray = [];
-                    var networkData = {
-                      zoneId: args.currentData.zoneid
-                    };
-
-                    if (!(cloudStack.context.projects && cloudStack.context.projects[0])) {
-                      networkData.domainid = g_domainid;
-                      networkData.account = g_account;
-                    }
-
-                    var networkObjs;
-                    $.ajax({
-                      url: createURL('listNetworks'),
-                      data: networkData,
-                      dataType: "json",
-                      async: false,
-                      success: function(json) {
-                        networkObjs = json.listnetworksresponse.network ? json.listnetworksresponse.network : [];
-                      }
-                    });
-
-																				
-										var apiCmd = "listNetworkOfferings&guestiptype=Isolated&supportedServices=sourceNat&state=Enabled&specifyvlan=false&zoneid=" + args.currentData.zoneid ; 
-										var array1 = [];
-                    var guestTrafficTypeTotal = 0;
-
-                    $.ajax({
-                      url: createURL(apiCmd + array1.join("")), //get the network offering for isolated network with sourceNat
-                      dataType: "json",
-                      async: false,
-                      success: function(json) {
-                        networkOfferingObjs  = json.listnetworkofferingsresponse.networkoffering;
-                      }
-                    });
-                    //get network offerings (end)	***			
-										
-										
-                    args.response.success({
-                      type: 'select-network',
-                      data: {
-                        myNetworks: [], //not used any more
-                        sharedNetworks: networkObjs,
-                        securityGroups: [],
-                        networkOfferings: networkOfferingObjs
-                      }
-                    });
-                  }
-
-                  else if(step5ContainerType == 'select-security-group') {
-                    var securityGroupArray = [];
-                    var data = {
-                      domainid: g_domainid,
-                      account: g_account
-                    };
-
-                    $.ajax({
-                      url: createURL("listSecurityGroups"),
-                      dataType: "json",
-                      async: false,
-                      data: cloudStack.context.projects ? {} : data,
-                      success: function(json) {
-                        var items = json.listsecuritygroupsresponse.securitygroup;
-                        if (items != null && items.length > 0) {
-                          for (var i = 0; i < items.length; i++) {
-                            if(items[i].name != "default") //exclude default security group because it is always applied
-                              securityGroupArray.push(items[i]);
-                          }
-                        }
-                      }
-                    });
-                    args.response.success({
-                      type: 'select-security-group',
-                      data: {
-                        myNetworks: [], //not used any more
-                        sharedNetworks: [],
-                        securityGroups: securityGroupArray,
-                        networkOfferings: []
-                      }
-                    });
-                  }
-
-                  else if(step5ContainerType == 'nothing-to-select') {
-                    args.response.success({
-                      type: 'nothing-to-select',
-                      data: {
-                        myNetworks: [], //not used any more
-                        sharedNetworks: [],
-                        securityGroups: [],
-                        networkOfferings: []
-                      }
-                    });
-                  }
-
-                },
-
-                          // Step 6: Review
-                          function(args) {
-                            return false;
-                          }
-                          ],
-              action: function(args) {
-                /*
-                 var isValid = true;
-                 isValid &= validateString("Name", $thisPopup.find("#wizard_vm_name"), $thisPopup.find("#wizard_vm_name_errormsg"), true);   //optional
-                 isValid &= validateString("Group", $thisPopup.find("#wizard_vm_group"), $thisPopup.find("#wizard_vm_group_errormsg"), true); //optional
-                 if (!isValid)
-                 return;
-                 */
-
-                // Create a new VM!!!!
-                var array1 = [];
-
-                //step 1 : select zone
-                array1.push("&zoneId=" + args.data.zoneid);
-
-                //step 2: select template
-                array1.push("&templateId=" + args.data.templateid);
-                array1.push("&hypervisor=" + selectedHypervisor);
-
-                //step 3: select service offering
-                array1.push("&serviceOfferingId=" + args.data.serviceofferingid);
-
-                //step 4: select disk offering
-                if(args.data.diskofferingid != null && args.data.diskofferingid != "0") {
-                  array1.push("&diskOfferingId=" + args.data.diskofferingid);
-                  if(selectedDiskOfferingObj.iscustomized == true)
-                    array1.push("&size=" + args.data.size);
-                }
-
-                //step 5: select network
-                if (step5ContainerType == 'select-network') {
-                  var array2 = [];
-                  var defaultNetworkId = args.data.defaultNetwork; //args.data.defaultNetwork might be equal to string "new-network" or a network ID
-
-                  var checkedNetworkIdArray;
-                  if(typeof(args.data["my-networks"]) == "object" && args.data["my-networks"].length != null) { //args.data["my-networks"] is an array of string, e.g. ["203", "202"],
-                    checkedNetworkIdArray = args.data["my-networks"];
-                  }
-                  else if(typeof(args.data["my-networks"]) == "string" && args.data["my-networks"].length > 0) { //args.data["my-networks"] is a string, e.g. "202"
-                    checkedNetworkIdArray = [];
-                    checkedNetworkIdArray.push(args.data["my-networks"]);
-                  }
-                  else { // typeof(args.data["my-networks"]) == null
-                    checkedNetworkIdArray = [];
-                  }
-
-                  //create new network starts here
-                  if(args.data["new-network"] == "create-new-network") {
-                    var isCreateNetworkSuccessful = true;
-                    $.ajax({
-                      url: createURL("createNetwork&networkOfferingId="+args.data["new-network-networkofferingid"]+"&name="+todb(args.data["new-network-name"])+"&displayText="+todb(args.data["new-network-name"])+"&zoneId="+selectedZoneObj.id),
-                      dataType: "json",
-                      async: false,
-                      success: function(json) {
-                        newNetwork = json.createnetworkresponse.network;
-                        checkedNetworkIdArray.push(newNetwork.id);
-                        if(defaultNetworkId == "new-network")
-                          defaultNetworkId = newNetwork.id;
-                      },
-                      error: function(XMLHttpResponse) {
-                        isCreateNetworkSuccessful = false;
-                        var errorMsg = "Failed to create new network, unable to proceed to deploy VM. Error: " + parseXMLHttpResponse(XMLHttpResponse);
-                        //alert(errorMsg);
-                        args.response.error(errorMsg);    //args.response.error(errorMsg) here doesn't show errorMsg. Waiting for Brian to fix it. use alert(errorMsg) to show errorMsg for now.
-                      }
-                    });
-                    if(isCreateNetworkSuccessful == false)
-                      return;
-                  }
-                  //create new network ends here
-
-                  //add default network first
-                  if(defaultNetworkId != null && defaultNetworkId.length > 0)
-                    array2.push(defaultNetworkId);
-
-                  //then, add other checked networks
-                  if(checkedNetworkIdArray.length > 0) {
-                    for(var i=0; i < checkedNetworkIdArray.length; i++) {
-                      if(checkedNetworkIdArray[i] != defaultNetworkId) //exclude defaultNetworkId that has been added to array2
-                        array2.push(checkedNetworkIdArray[i]);
-                    }
-                  }
-
-                  array1.push("&networkIds=" + array2.join(","));
-                }
-                else if (step5ContainerType == 'select-security-group') {
-                  var checkedSecurityGroupIdArray;
-                  if(typeof(args.data["security-groups"]) == "object" && args.data["security-groups"].length != null) { //args.data["security-groups"] is an array of string, e.g. ["2375f8cc-8a73-4b8d-9b26-50885a25ffe0", "27c60d2a-de7f-4bb7-96e5-a602cec681df","c6301d77-99b5-4e8a-85e2-3ea2ab31c342"],
-                    checkedSecurityGroupIdArray = args.data["security-groups"];
-                  }
-                  else if(typeof(args.data["security-groups"]) == "string" && args.data["security-groups"].length > 0) { //args.data["security-groups"] is a string, e.g. "2375f8cc-8a73-4b8d-9b26-50885a25ffe0"
-                    checkedSecurityGroupIdArray = [];
-                    checkedSecurityGroupIdArray.push(args.data["security-groups"]);
-                  }
-                  else { // typeof(args.data["security-groups"]) == null
-                    checkedSecurityGroupIdArray = [];
-                  }
-
-                  if(checkedSecurityGroupIdArray.length > 0)
-                    array1.push("&securitygroupids=" + checkedSecurityGroupIdArray.join(","));
-                }
-
-                var displayname = args.data.displayname;
-                if(displayname != null && displayname.length > 0) {
-                  array1.push("&displayname="+todb(displayname));
-									array1.push("&name="+todb(displayname));
-								}
-
-                var group = args.data.groupname;
-                if (group != null && group.length > 0)
-                  array1.push("&group="+todb(group));
-
-								//array1.push("&startVm=false");	//for testing only, comment it out before checking in
-									
-                $.ajax({
-                  url: createURL("deployVirtualMachine"+array1.join("")),
-                  dataType: "json",
-                  success: function(json) {
-                    var jid = json.deployvirtualmachineresponse.jobid;
-					          var vmid = json.deployvirtualmachineresponse.id;
-                    args.response.success(
-                      {_custom:
-                       {jobId: jid,
-                        getUpdatedItem: function(json) {
-                          var item = json.queryasyncjobresultresponse.jobresult.virtualmachine;
-                          if (item.password != null)
-                            alert("Password of new VM " + item.displayname + " is  " + item.password);
-                          return item;
-                        },
-                        getActionFilter: function() {
-                          return vmActionfilter;
-                        },
-												getUpdatedItemWhenAsyncJobFails: function() {
-													var item;
-													$.ajax({
-														url: createURL("listVirtualMachines&id="+vmid),
-														dataType: "json",
-														async: false,
-														success: function(json) {
-														item = json.listvirtualmachinesresponse.virtualmachine[0];
-														}
-													});
-													return item;
-												}
-                       }
-                      }
-                    );
-                  },
-                  error: function(XMLHttpResponse) {
-                    args.response.error(parseXMLHttpResponse(XMLHttpResponse)); //wait for Brian to implement
-                  }
-                });
-              }
-            })
+            custom: cloudStack.uiCustom.instanceWizard(cloudStack.instanceWizard)
           },
 
           messages: {            

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c347c6bd/ui/scripts/network.js
----------------------------------------------------------------------
diff --git a/ui/scripts/network.js b/ui/scripts/network.js
index 597186e..150ade2 100644
--- a/ui/scripts/network.js
+++ b/ui/scripts/network.js
@@ -177,7 +177,7 @@
           }
         });
 
-        var sectionsToShow = ['networks'];
+        var sectionsToShow = ['networks', 'vpc'];
         if(havingSecurityGroupNetwork == true)
           sectionsToShow.push('securityGroups');
 
@@ -3105,6 +3105,91 @@
             }
           }
         }
+      },
+      vpc: {
+        type: 'select',
+        title: 'VPC',
+        id: 'vpc',
+        listView: {
+          id: 'vpc',
+          label: 'VPC',
+          fields: {
+            name: { label: 'Name' },
+            zone: { label: 'Zone' },
+            cidr: { label: 'CIDR' }
+          },
+          dataProvider: function(args) {
+            args.response.success({
+              data: [
+                {
+                  name: 'VPC 1',
+                  zone: 'San Jose',
+                  cidr: '0.0.0.0/0',
+                  networkdomain: 'testdomain',
+                  accountdomain: 'testdomain'
+                },
+                {
+                  name: 'VPC 2',
+                  zone: 'San Jose',
+                  cidr: '0.0.0.0/0',
+                  networkdomain: 'testdomain',
+                  accountdomain: 'testdomain'
+                },
+                {
+                  name: 'VPC 3',
+                  zone: 'Cupertino',
+                  cidr: '0.0.0.0/0',
+                  networkdomain: 'testdomain',
+                  accountdomain: 'testdomain'
+                },
+                {
+                  name: 'VPC 4',
+                  zone: 'San Jose',
+                  cidr: '0.0.0.0/0',
+                  networkdomain: 'testdomain',
+                  accountdomain: 'testdomain'
+                }
+              ]
+            });
+          },
+          actions: {
+            add: {
+              label: 'Add VPC',
+              createForm: {
+                title: 'Add new VPC',
+                fields: {
+                  name: { label: 'Name', validation: { required: true } },
+                  zone: {
+                    label: 'Zone',
+                    validation: { required: true },
+                    select: function(args) {
+                      args.response.success({
+                        data: [
+                          { id: 'zone1', description: 'Zone 1' },
+                          { id: 'zone2', description: 'Zone 2' },
+                          { id: 'zone3', description: 'Zone 3' }
+                        ]
+                      });
+                    }
+                  }
+                }
+              },
+              messages: {
+                notification: function(args) { return 'Add new VPC'; }
+              },
+              action: function(args) {
+                args.response.success();
+              },
+              notification: { poll: function(args) { args.complete(); } }
+            },
+            editVpc: {
+              label: 'Edit VPC',
+              action: {
+                custom: cloudStack.uiCustom.vpc(cloudStack.vpc)
+              }
+            }
+          }
+        }
       }
     }
   };

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c347c6bd/ui/scripts/ui-custom/instanceWizard.js
----------------------------------------------------------------------
diff --git a/ui/scripts/ui-custom/instanceWizard.js b/ui/scripts/ui-custom/instanceWizard.js
index 4c1d791..0dfcdf9 100644
--- a/ui/scripts/ui-custom/instanceWizard.js
+++ b/ui/scripts/ui-custom/instanceWizard.js
@@ -18,7 +18,7 @@
   /**
    * Instance wizard
    */
-  cloudStack.instanceWizard = function(args) {
+  cloudStack.uiCustom.instanceWizard = function(args) {
     return function(listViewArgs) {
       var context = listViewArgs.context;
 

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c347c6bd/ui/scripts/ui-custom/vpc.js
----------------------------------------------------------------------
diff --git a/ui/scripts/ui-custom/vpc.js b/ui/scripts/ui-custom/vpc.js
new file mode 100644
index 0000000..3804386
--- /dev/null
+++ b/ui/scripts/ui-custom/vpc.js
@@ -0,0 +1,404 @@
+(function($, cloudStack) {
+  var elems = {
+    router: function() {
+      var $router = $('<li>').addClass('tier virtual-router');
+      var $title = $('<span>').addClass('title').html('Virtual Router');
+
+      $router.append($title);
+
+      // Append horizontal chart line
+      $router.append($('<div>').addClass('connect-line'));
+
+      return $router;
+    },
+    tier: function(args) {
+      var name = args.name;
+      var cidr = args.cidr;
+      var context = args.context;
+      var vmListView = args.vmListView;
+      var disabledActions = args.actionPreFilter ? args.actionPreFilter({
+        context: context
+      }) : true;
+      var actions = $.map(
+        args.actions ? args.actions : {}, function(value, key) {
+          return {
+            id: key,
+            action: value,
+            isDisabled: $.isArray(disabledActions) &&
+              $.inArray(key, disabledActions) != -1
+          };
+        }
+      );
+      var isPlaceholder = args.isPlaceholder;
+      var virtualMachines = args.virtualMachines;
+      var $tier = $('<li>').addClass('tier');
+      var $title = $('<span>').addClass('title');
+      var $cidr = $('<span>').addClass('cidr');
+      var $vmCount = $('<span>').addClass('vm-count');
+      var $actions = $('<div>').addClass('actions');
+
+      // Ignore special actions
+      // -- Add tier action is handled separately
+      actions = $.grep(actions, function(action) {
+        return action.id != 'add';
+      });
+
+      // VM count shows instance list
+      $vmCount.click(function() {
+        var $dialog = $('<div>');
+        var $listView = $('<div>').listView($.extend(true, {}, vmListView, {
+          context: context
+        }));
+
+        $dialog.append($listView);
+        $dialog.dialog({
+          title: 'VMs in this tier',
+          dialogClass: 'multi-edit-add-list panel configure-acl',
+          width: 825,
+          height: 600,
+          buttons: {
+            'Done': function() {
+              $(':ui-dialog').remove();
+              $('.overlay').remove();
+            }
+          }
+        }).closest('.ui-dialog').overlay();
+      });
+
+      if (isPlaceholder) {
+        $tier.addClass('placeholder');
+        $title.html('Create Tier');
+      } else {
+        $title.html(name);
+        $cidr.html(cidr);
+        $vmCount.append(
+          $('<span>').addClass('total').html(virtualMachines.length),
+          ' VMs'
+        );
+        $tier.append($actions);
+
+        // Build action buttons
+        $(actions).map(function(index, action) {
+          var $action = $('<div>').addClass('action');
+          var shortLabel = action.action.shortLabel;
+          var label = action.action.label;
+          var isDisabled = action.isDisabled;
+
+          $action.addClass(action.id);
+
+          if (action.id != 'remove') {
+            $action.append($('<span>').addClass('label').html(shortLabel));
+          } else {
+            $action.append($('<span>').addClass('icon').html('&nbsp;'));
+          }
+          $actions.append($action);
+          $action.attr('title', label);
+
+          if (isDisabled) $action.addClass('disabled');
+
+          // Action event
+          $action.click(function() {
+            if (isDisabled) {
+              return false;
+            }
+                
+            tierAction({
+              action: action,
+              context: context,
+              $tier: $tier
+            });
+
+            return true;
+          });
+        });
+      }
+
+      $tier.prepend($title);
+
+      if (!isPlaceholder) {
+        $tier.append($title, $cidr, $vmCount);
+      }
+
+      // Append horizontal chart line
+      $tier.append($('<div>').addClass('connect-line'));
+
+      return $tier;
+    },
+    chart: function(args) {
+      var tiers = args.tiers;
+      var vmListView = args.vmListView;
+      var actions = args.actions;
+      var actionPreFilter = args.actionPreFilter;
+      var vpcName = args.vpcName;
+      var context = args.context;
+      var $tiers = $('<ul>').addClass('tiers');
+      var $router = elems.router();
+      var $chart = $('<div>').addClass('vpc-chart');
+      var $title = $('<div>').addClass('vpc-title').html(vpcName);
+
+      var showAddTierDialog = function() {
+        if ($(this).find('.loading-overlay').size()) {
+          return false;
+        }
+        
+        addTierDialog({
+          $tiers: $tiers,
+          context: context,
+          actions: actions,
+          vmListView: vmListView,
+          actionPreFilter: actionPreFilter
+        });
+
+        return true;
+      };
+
+      if (tiers.length) {
+        $(tiers).map(function(index, tier) {
+          var $tier = elems.tier({
+            name: tier.name,
+            cidr: tier.cidr,
+            virtualMachines: tier.virtualMachines,
+            vmListView: vmListView,
+            actions: actions,
+            actionPreFilter: actionPreFilter,
+            context: $.extend(true, {}, context, {
+              tiers: [tier]
+            })
+          });
+
+          $tier.appendTo($tiers);
+        });
+
+      }
+
+      elems.tier({ isPlaceholder: true }).appendTo($tiers)
+        .click(showAddTierDialog);
+      $tiers.prepend($router);
+      $chart.append($title, $tiers);
+
+      if (!tiers || !tiers.length) {
+        showAddTierDialog();
+      }
+
+      return $chart;
+    }
+  };
+
+  // Handles tier action, including UI effects
+  var tierAction = function(args) {
+    var $tier = args.$tier;
+    var $loading = $('<div>').addClass('loading-overlay');
+    var actionArgs = args.action.action;
+    var action = actionArgs.action;
+    var actionID = args.action.id;
+    var notification = actionArgs.notification;
+    var label = actionArgs.label;
+    var context = args.context;
+
+    var success = function(args) {
+      var remove = args ? args.remove : false;
+
+      cloudStack.ui.notifications.add(
+        // Notification
+        {
+          desc: label,
+          poll: notification.poll
+        },
+
+        // Success
+        function(args) {
+          if (remove) {
+            $tier.remove();
+          } else {
+            $loading.remove();
+          }
+
+          if (actionID == 'addVM') {
+            // Increment VM total
+            var $total = $tier.find('.vm-count .total');
+            var prevTotal = parseInt($total.html());
+            var newTotal = prevTotal + 1;
+
+            $total.html(newTotal);
+          }
+        },
+
+        {},
+
+        // Error
+        function(args) {
+          $loading.remove();
+        }
+      );
+    };
+
+    switch(actionID) {
+      case 'addVM':
+        action({
+          context: context,
+          complete: function(args) {
+            $loading.appendTo($tier);
+            success(args);
+          }
+        });
+        break;
+      case 'remove':
+        $loading.appendTo($tier);
+        action({
+          context: context,
+          response: {
+            success: function(args) {
+              success({ remove: true });
+            }
+          }
+        });
+        break;
+      case 'acl':
+      // Show ACL dialog
+      $('<div>').multiEdit(
+        $.extend(true, {}, actionArgs.multiEdit, {
+          context: context
+        })
+      ).dialog({
+        title: 'Configure ACL',
+        dialogClass: 'configure-acl',
+        width: 820,
+        height: 600,
+        buttons: {
+          'Done': function() {
+            $(':ui-dialog').remove();
+            $('.overlay').remove();
+          }
+        }
+      }).closest('.ui-dialog').overlay();
+      break;
+      default:
+        $loading.appendTo($tier);
+        action({
+          context: context,
+          complete: success,
+          response: {
+            success: success,
+            error: function(args) { $loading.remove(); }
+          }
+        });
+    }
+  };
+
+  // Appends a new tier to chart
+  var addNewTier = function(args) {
+    var actions = args.actions;
+    var vmListView = args.vmListView;
+    var actionPreFilter = args.actionPreFilter;
+    var tier = $.extend(args.tier, {
+      vmListView: vmListView,
+      actions: actions,
+      actionPreFilter: actionPreFilter,
+      virtualMachines: []
+    });
+    var $tiers = args.$tiers;
+
+    $tiers.find('li.placeholder')
+      .before(
+        elems.tier(tier)
+          .hide()
+          .fadeIn('slow')
+      );
+  };
+
+  // Renders the add tier form, in a dialog
+  var addTierDialog = function(args) {
+    var actions = args.actions;
+    var context = args.context;
+    var vmListView = args.vmListView;
+    var actionPreFilter = args.actionPreFilter;
+    var $tiers = args.$tiers;
+
+    cloudStack.dialog.createForm({
+      form: actions.add.createForm,
+      after: function(args) {
+        var $loading = $('<div>').addClass('loading-overlay').prependTo($tiers.find('li.placeholder'));
+        actions.add.action({
+          context: context,
+          data: args.data,
+          response: {
+            success: function(args) {
+              var tier = args.data;
+              
+              cloudStack.ui.notifications.add(
+                // Notification
+                {
+                  desc: actions.add.label,
+                  poll: actions.add.notification.poll
+                },
+
+                // Success
+                function(args) {
+                  $loading.remove();
+                  addNewTier({
+                    tier: tier,
+                    $tiers: $tiers,
+                    actions: actions,
+                    actionPreFilter: actionPreFilter,
+                    vmListView: vmListView
+                  });
+                },
+
+                {},
+
+                // Error
+                function(args) {
+                  $loading.remove();
+                }
+              );
+            }
+          }
+        });
+      }
+    });
+  };
+
+  cloudStack.uiCustom.vpc = function(args) {
+    var vmListView = args.vmListView;
+    var tierArgs = args.tiers;
+
+    return function(args) {
+      var context = args.context;
+      var $browser = $('#browser .container');
+      var $toolbar = $('<div>').addClass('toolbar');
+      var vpc = args.context.vpc[0];
+
+      $browser.cloudBrowser('addPanel', {
+        maximizeIfSelected: true,
+        title: 'Configure VPC: ' + vpc.name,
+        complete: function($panel) {
+          var $loading = $('<div>').addClass('loading-overlay').appendTo($panel);
+
+          $panel.append($toolbar);
+
+          // Load data
+          tierArgs.dataProvider({
+            context: context,
+            response: {
+              success: function(args) {
+                var tiers = args.data.tiers;
+                var $chart = elems.chart({
+                  vmListView: vmListView,
+                  context: context,
+                  actions: tierArgs.actions,
+                  actionPreFilter: tierArgs.actionPreFilter,
+                  vpcName: vpc.name,
+                  tiers: tiers
+                }).appendTo($panel);
+
+                $loading.remove();
+                $chart.fadeIn(function() {
+                });
+              }
+            }
+          });
+        }
+      });
+    };
+  };
+}(jQuery, cloudStack));
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c347c6bd/ui/scripts/vpc.js
----------------------------------------------------------------------
diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js
new file mode 100644
index 0000000..a3b9afb
--- /dev/null
+++ b/ui/scripts/vpc.js
@@ -0,0 +1,469 @@
+(function($, cloudStack) {
+  var aclMultiEdit = {
+    noSelect: true,
+    fields: {
+      'cidrlist': { edit: true, label: 'Source CIDR' },
+      'protocol': {
+        label: 'Protocol',
+        select: function(args) {
+          args.$select.change(function() {
+            var $inputs = args.$form.find('input');
+            var $icmpFields = $inputs.filter(function() {
+              var name = $(this).attr('name');
+
+              return $.inArray(name, [
+                'icmptype',
+                'icmpcode'
+              ]) > -1;
+            });
+            var $otherFields = $inputs.filter(function() {
+              var name = $(this).attr('name');
+
+              return name != 'icmptype' && name != 'icmpcode' && name != 'cidrlist';
+            });
+
+            if ($(this).val() == 'icmp') {
+              $icmpFields.attr('disabled', false);
+              $otherFields.attr('disabled', 'disabled');
+            } else {
+              $otherFields.attr('disabled', false);
+              $icmpFields.attr('disabled', 'disabled');
+            }
+          });
+
+          args.response.success({
+            data: [
+              { name: 'tcp', description: 'TCP' },
+              { name: 'udp', description: 'UDP' },
+              { name: 'icmp', description: 'ICMP' }
+            ]
+          });
+        }
+      },
+      'startport': { edit: true, label: 'Start Port' },
+      'endport': { edit: true, label: 'End Port' },
+      'icmptype': { edit: true, label: 'ICMP Type', isDisabled: true },
+      'icmpcode': { edit: true, label: 'ICMP Code', isDisabled: true },
+      'add-rule': {
+        label: 'Add',
+        addButton: true
+      }
+    },
+    add: {
+      label: 'Add',
+      action: function(args) {
+        setTimeout(function() {
+          args.response.success({
+            notification: {
+              label: 'Add ACL rule',
+              poll: function(args) { args.complete(); }
+            }
+          });
+        }, 500);
+      }
+    },
+    actions: {
+      destroy: {
+        label: 'Remove Rule',
+        action: function(args) {
+          setTimeout(function() {
+            args.response.success({
+              notification: {
+                label: 'Remove ACL rule',
+                poll: function(args) { args.complete(); }
+              }
+            });
+          }, 500);
+        }
+      }
+    },
+    dataProvider: function(args) {
+      setTimeout(function() {
+        args.response.success({
+          data: [
+            {
+              "id": 11,
+              "protocol": "icmp",
+              "ipaddressid": 4,
+              "ipaddress": "10.223.71.23",
+              "state": "Active",
+              "cidrlist": "0.0.0.0/0",
+              "icmptype": 2,
+              "icmpcode": 22
+            },
+            {
+              "id": 10,
+              "protocol": "udp",
+              "startport": "500",
+              "endport": "10000",
+              "ipaddressid": 4,
+              "ipaddress": "10.223.71.23",
+              "state": "Active",
+              "cidrlist": "0.0.0.0/24"
+            },
+            {
+              "id": 9,
+              "protocol": "tcp",
+              "startport": "20",
+              "endport": "200",
+              "ipaddressid": 4,
+              "ipaddress": "10.223.71.23",
+              "state": "Active",
+              "cidrlist": "0.0.0.0/24"
+            },
+            {
+              "id": 11,
+              "protocol": "icmp",
+              "ipaddressid": 4,
+              "ipaddress": "10.223.71.23",
+              "state": "Active",
+              "cidrlist": "0.0.0.0/0",
+              "icmptype": 2,
+              "icmpcode": 22
+            },
+            {
+              "id": 10,
+              "protocol": "udp",
+              "startport": "500",
+              "endport": "10000",
+              "ipaddressid": 4,
+              "ipaddress": "10.223.71.23",
+              "state": "Active",
+              "cidrlist": "0.0.0.0/24"
+            },
+            {
+              "id": 9,
+              "protocol": "tcp",
+              "startport": "20",
+              "endport": "200",
+              "ipaddressid": 4,
+              "ipaddress": "10.223.71.23",
+              "state": "Active",
+              "cidrlist": "0.0.0.0/24"
+            },
+            {
+              "id": 11,
+              "protocol": "icmp",
+              "ipaddressid": 4,
+              "ipaddress": "10.223.71.23",
+              "state": "Active",
+              "cidrlist": "0.0.0.0/0",
+              "icmptype": 2,
+              "icmpcode": 22
+            },
+            {
+              "id": 10,
+              "protocol": "udp",
+              "startport": "500",
+              "endport": "10000",
+              "ipaddressid": 4,
+              "ipaddress": "10.223.71.23",
+              "state": "Active",
+              "cidrlist": "0.0.0.0/24"
+            },
+            {
+              "id": 9,
+              "protocol": "tcp",
+              "startport": "20",
+              "endport": "200",
+              "ipaddressid": 4,
+              "ipaddress": "10.223.71.23",
+              "state": "Active",
+              "cidrlist": "0.0.0.0/24"
+            },
+            {
+              "id": 11,
+              "protocol": "icmp",
+              "ipaddressid": 4,
+              "ipaddress": "10.223.71.23",
+              "state": "Active",
+              "cidrlist": "0.0.0.0/0",
+              "icmptype": 2,
+              "icmpcode": 22
+            },
+            {
+              "id": 10,
+              "protocol": "udp",
+              "startport": "500",
+              "endport": "10000",
+              "ipaddressid": 4,
+              "ipaddress": "10.223.71.23",
+              "state": "Active",
+              "cidrlist": "0.0.0.0/24"
+            },
+            {
+              "id": 9,
+              "protocol": "tcp",
+              "startport": "20",
+              "endport": "200",
+              "ipaddressid": 4,
+              "ipaddress": "10.223.71.23",
+              "state": "Active",
+              "cidrlist": "0.0.0.0/24"
+            },
+            {
+              "id": 11,
+              "protocol": "icmp",
+              "ipaddressid": 4,
+              "ipaddress": "10.223.71.23",
+              "state": "Active",
+              "cidrlist": "0.0.0.0/0",
+              "icmptype": 2,
+              "icmpcode": 22
+            },
+            {
+              "id": 10,
+              "protocol": "udp",
+              "startport": "500",
+              "endport": "10000",
+              "ipaddressid": 4,
+              "ipaddress": "10.223.71.23",
+              "state": "Active",
+              "cidrlist": "0.0.0.0/24"
+            },
+            {
+              "id": 9,
+              "protocol": "tcp",
+              "startport": "20",
+              "endport": "200",
+              "ipaddressid": 4,
+              "ipaddress": "10.223.71.23",
+              "state": "Active",
+              "cidrlist": "0.0.0.0/24"
+            }
+          ]
+        });
+      }, 100);
+    }
+  };
+  
+  cloudStack.vpc = {
+    vmListView: {
+      id: 'vpcTierInstances',
+      listView: {
+        filters: {
+          mine: { label: 'My instances' },
+          all: { label: 'All instances' },
+          running: { label: 'Running instances' },
+          destroyed: { label: 'Destroyed instances' }
+        },
+        fields: {
+          name: { label: 'Name', editable: true },
+          account: { label: 'Account' },
+          zonename: { label: 'Zone' },
+          state: {
+            label: 'Status',
+            indicator: {
+              'Running': 'on',
+              'Stopped': 'off',
+              'Destroyed': 'off'
+            }
+          }
+        },
+
+        // List view actions
+        actions: {
+          restart: {
+            label: 'Restart instance',
+            action: function(args) {
+              setTimeout(function() {
+                args.response.success({
+                  data: {
+                    state: 'Restarting'
+                  }
+                });
+              }, 1000);
+            },
+            messages: {
+              confirm: function(args) {
+                return 'Are you sure you want to restart ' + args.name + '?';
+              },
+              notification: function(args) {
+                return 'Rebooting VM: ' + args.name;
+              }
+            },
+            notification: {
+              poll: function(args) { args.complete(); }
+            }
+          },
+          stop: {
+            label: 'Stop instance',
+            action: function(args) {
+              setTimeout(function() {
+                args.response.success({
+                  data: { state: 'Stopping' }
+                });
+              }, 500);
+            },
+            messages: {
+              confirm: function(args) {
+                return 'Are you sure you want to shutdown ' + args.name + '?';
+              },
+              notification: function(args) {
+                return 'Rebooting VM: ' + args.name;
+              }
+            },
+            notification: {
+              poll: function(args) { args.complete(); }
+            }
+          },
+          start: {
+            label: 'Start instance',
+            action: function(args) {
+              setTimeout(function() {
+                args.response.success({
+                  data: { state: 'Starting' }
+                });
+              }, 500);
+            },
+            messages: {
+              confirm: function(args) {
+                return 'Are you sure you want to start ' + args.name + '?';
+              },
+              notification: function(args) {
+                return 'Starting VM: ' + args.name;
+              }
+            },
+            notification: {
+              poll: function(args) { args.complete(); }
+            }
+          },
+          destroy: {
+            label: 'Destroy instance',
+            messages: {
+              confirm: function(args) {
+                return 'Are you sure you want to destroy ' + args.name + '?';
+              },
+              notification: function(args) {
+                return 'Destroyed VM: ' + args.name;
+              }
+            },
+            action: function(args) {
+              setTimeout(function() {
+                args.response.success({ data: { state: 'Destroying' }});
+              }, 200);
+            },
+            notification: {
+              poll: function(args) { args.complete(); }
+            }
+          }
+        },
+        dataProvider: function(args) {
+          $.ajax({
+            url: createURL('listVirtualMachines'),
+            success: function(json) {
+              args.response.success({ data: json.listvirtualmachinesresponse.virtualmachine });
+            }
+          });
+        }
+      }
+    },
+    tiers: {
+      actionPreFilter: function(args) {
+        return ['start'];
+      },
+      actions: {
+        // Add new tier
+        add: {
+          label: 'Add new tier to VPC',
+          action: function(args) {
+            setTimeout(function() {
+              args.response.success({
+                data: {
+                  name: args.data.name,
+                  cidr: args.data.cidr
+                }
+              });
+            }, 500);
+          },
+
+          createForm: {
+            title: 'Add new tier',
+            desc: 'Please fill in the following to add a new VPC tier.',
+            fields: {
+              name: { label: 'label.name', validation: { required: true } },
+              cidr: { label: 'label.cidr', validation: { required: true } }
+            }
+          },
+
+          notification: {
+            poll: function(args) { args.complete(); }
+          }
+        },
+        start: {
+          label: 'Start tier',
+          shortLabel: 'Start',
+          action: function(args) {
+            args.response.success();
+          },
+          notification: {
+            poll: function(args) { args.complete(); }
+          }
+        },
+        stop: {
+          label: 'Stop tier',
+          shortLabel: 'Stop',
+          action: function(args) {
+            args.response.success();
+          },
+          notification: {
+            poll: function(args) { args.complete(); }
+          }
+        },
+        addVM: {
+          label: 'Add VM to tier',
+          shortLabel: 'Add VM',
+          action: cloudStack.uiCustom.instanceWizard(
+            cloudStack.instanceWizard
+          ),
+          notification: {
+            poll: function(args) { args.complete(); }
+          }
+        },
+        acl: {
+          label: 'Configure ACL for tier',
+          shortLabel: 'ACL',
+          multiEdit: aclMultiEdit
+        },
+        remove: {
+          label: 'Remove tier',
+          action: function(args) {
+            args.response.success();
+          },
+          notification: {
+            poll: function(args) { args.complete(); }
+          }
+        }
+      },
+
+      // Get tiers
+      dataProvider: function(args) {
+        var tiers = [ // Dummy content
+          {
+            id: 1,
+            name: 'web',
+            cidr: '192.168.0.0/24',
+            virtualMachines: [
+              { name: 'i-2-VM' },
+              { name: 'i-3-VM' }
+            ]
+          },
+          {
+            id: 2,
+            name: 'app',
+            cidr: '10.0.0.0/24',
+            virtualMachines: []
+          }
+        ];
+
+        setTimeout(function() {
+          args.response.success({
+            data: {
+              tiers: tiers
+            }
+          });
+        }, 1000);
+      }
+    }
+  };
+}(jQuery, cloudStack));