You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ki...@apache.org on 2013/11/07 15:38:25 UTC

git commit: updated refs/heads/master to 3f5b8f7

Updated Branches:
  refs/heads/master 85f38b3e0 -> 3f5b8f706


CLOUDSTACK-4793 : Added UpgradeRouterTemplate API. Added filters to listRouters API. listRouters response includes verion and required upgrade flag. Min VR version is checked before sending commands to router


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

Branch: refs/heads/master
Commit: 3f5b8f70630e8415a611984ccde2e1f631e96bc9
Parents: 85f38b3
Author: Kishan Kavala <ki...@cloud.com>
Authored: Thu Nov 7 19:42:19 2013 +0530
Committer: Kishan Kavala <ki...@cloud.com>
Committed: Thu Nov 7 19:49:05 2013 +0530

----------------------------------------------------------------------
 .../network/VirtualNetworkApplianceService.java |   6 +
 .../com/cloud/network/router/VirtualRouter.java |   1 +
 .../org/apache/cloudstack/api/ApiConstants.java |   1 +
 .../cloudstack/api/ResponseGenerator.java       |   4 +
 .../command/admin/router/ListRoutersCmd.java    |  11 +-
 .../admin/router/UpgradeRouterTemplateCmd.java  | 143 +++++++++++++++++++
 .../api/response/DomainRouterResponse.java      |  23 ++-
 .../response/UpgradeRouterTemplateResponse.java |  45 ++++++
 client/tomcatconf/commands.properties.in        |   1 +
 .../src/com/cloud/vm/dao/DomainRouterDao.java   |   3 +-
 .../com/cloud/vm/dao/DomainRouterDaoImpl.java   |   7 +
 server/src/com/cloud/api/ApiResponseHelper.java |  17 +++
 .../com/cloud/api/query/QueryManagerImpl.java   |  12 +-
 .../com/cloud/api/query/ViewResponseHelper.java |   2 +
 .../api/query/dao/DomainRouterJoinDaoImpl.java  |   7 +
 .../VirtualNetworkApplianceManagerImpl.java     | 109 +++++++++++++-
 .../com/cloud/server/ManagementServerImpl.java  |   2 +
 .../MockVpcVirtualNetworkApplianceManager.java  |   7 +-
 utils/src/com/cloud/maint/Version.java          |   8 ++
 19 files changed, 394 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3f5b8f70/api/src/com/cloud/network/VirtualNetworkApplianceService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/VirtualNetworkApplianceService.java b/api/src/com/cloud/network/VirtualNetworkApplianceService.java
index 58eead2..fb5d12a 100644
--- a/api/src/com/cloud/network/VirtualNetworkApplianceService.java
+++ b/api/src/com/cloud/network/VirtualNetworkApplianceService.java
@@ -23,6 +23,9 @@ import com.cloud.exception.InsufficientCapacityException;
 import com.cloud.exception.ResourceUnavailableException;
 import com.cloud.network.router.VirtualRouter;
 import com.cloud.user.Account;
+import org.apache.cloudstack.api.command.admin.router.UpgradeRouterTemplateCmd;
+
+import java.util.List;
 
 public interface VirtualNetworkApplianceService {
     /**
@@ -66,4 +69,7 @@ public interface VirtualNetworkApplianceService {
     
     VirtualRouter findRouter(long routerId);
 
+    List<Long> upgradeRouterTemplate(UpgradeRouterTemplateCmd cmd);
+
+    public static final String _minVRVersion = "4.2.0";
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3f5b8f70/api/src/com/cloud/network/router/VirtualRouter.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/router/VirtualRouter.java b/api/src/com/cloud/network/router/VirtualRouter.java
index 9e90e8e..a875218 100755
--- a/api/src/com/cloud/network/router/VirtualRouter.java
+++ b/api/src/com/cloud/network/router/VirtualRouter.java
@@ -41,4 +41,5 @@ public interface VirtualRouter extends VirtualMachine {
      * @return
      */
     Long getVpcId();
+    String getTemplateVersion();
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3f5b8f70/api/src/org/apache/cloudstack/api/ApiConstants.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java
index 20e848d..bd52593 100755
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -528,6 +528,7 @@ public class ApiConstants {
     public static final String EXPUNGE = "expunge";
     public static final String FOR_DISPLAY = "fordisplay";
     public static final String PASSIVE = "passive";
+    public static final String VERSION = "version";
 
     public enum HostDetails {
         all, capacity, events, stats, min;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3f5b8f70/api/src/org/apache/cloudstack/api/ResponseGenerator.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/org/apache/cloudstack/api/ResponseGenerator.java
index a8de31d..832f6e3 100644
--- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java
+++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java
@@ -60,6 +60,7 @@ import org.apache.cloudstack.api.response.IpForwardingRuleResponse;
 import org.apache.cloudstack.api.response.IsolationMethodResponse;
 import org.apache.cloudstack.api.response.LBHealthCheckResponse;
 import org.apache.cloudstack.api.response.LBStickinessResponse;
+import org.apache.cloudstack.api.response.ListResponse;
 import org.apache.cloudstack.api.response.LoadBalancerResponse;
 import org.apache.cloudstack.api.response.NetworkACLItemResponse;
 import org.apache.cloudstack.api.response.NetworkACLResponse;
@@ -99,6 +100,7 @@ import org.apache.cloudstack.api.response.TemplatePermissionsResponse;
 import org.apache.cloudstack.api.response.TemplateResponse;
 import org.apache.cloudstack.api.response.TrafficMonitorResponse;
 import org.apache.cloudstack.api.response.TrafficTypeResponse;
+import org.apache.cloudstack.api.response.UpgradeRouterTemplateResponse;
 import org.apache.cloudstack.api.response.UsageRecordResponse;
 import org.apache.cloudstack.api.response.UserResponse;
 import org.apache.cloudstack.api.response.UserVmResponse;
@@ -446,4 +448,6 @@ public interface ResponseGenerator {
 
     IsolationMethodResponse createIsolationMethodResponse(IsolationType method);
 
+    ListResponse<UpgradeRouterTemplateResponse> createUpgradeRouterTemplateResponse(List<Long> jobIds);
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3f5b8f70/api/src/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java b/api/src/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java
index d7f59b96..2752a13 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java
@@ -75,7 +75,10 @@ public class ListRoutersCmd extends BaseListProjectAndAccountResourcesCmd {
 
     @Parameter(name=ApiConstants.FOR_VPC, type=CommandType.BOOLEAN, description="if true is passed for this parameter, list only VPC routers")
     private Boolean forVpc;
-    
+
+    @Parameter(name=ApiConstants.VERSION, type=CommandType.STRING, description="list virtual router elements by version")
+    private String version;
+
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -115,7 +118,11 @@ public class ListRoutersCmd extends BaseListProjectAndAccountResourcesCmd {
     public Boolean getForVpc() {
         return forVpc;
     }
-    
+
+    public String getVersion() {
+        return version;
+    }
+
     public String getRole() {
         return Role.VIRTUAL_ROUTER.toString();
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3f5b8f70/api/src/org/apache/cloudstack/api/command/admin/router/UpgradeRouterTemplateCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/router/UpgradeRouterTemplateCmd.java b/api/src/org/apache/cloudstack/api/command/admin/router/UpgradeRouterTemplateCmd.java
new file mode 100644
index 0000000..1db22bc
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/router/UpgradeRouterTemplateCmd.java
@@ -0,0 +1,143 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.command.admin.router;
+
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.router.VirtualRouter;
+import com.cloud.user.Account;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.ClusterResponse;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.DomainRouterResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.PodResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.api.response.UpgradeRouterTemplateResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.cloudstack.context.CallContext;
+
+import java.util.List;
+import java.util.logging.Logger;
+
+@APICommand(name = "upgradeRouterTemplate", description="Upgrades router to use newer template", responseObject=BaseResponse.class)
+public class UpgradeRouterTemplateCmd extends org.apache.cloudstack.api.BaseCmd {
+    public static final Logger s_logger = Logger.getLogger(UpgradeRouterTemplateCmd.class.getName());
+    private static final String s_name = "upgraderoutertemplateresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name= ApiConstants.ID, type=CommandType.UUID, entityType = DomainRouterResponse.class,
+            description="upgrades router with the specified Id")
+    private Long id;
+
+    @Parameter(name=ApiConstants.CLUSTER_ID, type=CommandType.UUID, entityType= ClusterResponse.class,
+            description="upgrades all routers within the specified cluster")
+    private Long clusterId;
+
+    @Parameter(name=ApiConstants.POD_ID, type=CommandType.UUID, entityType=PodResponse.class,
+            description="upgrades all routers within the specified pod")
+    private Long podId;
+
+    @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType=ZoneResponse.class,
+            description="upgrades all routers within the specified zone")
+    private Long zoneId;
+
+    @Parameter(name=ApiConstants.ACCOUNT_ID, type=CommandType.UUID, entityType = AccountResponse.class,
+            description="upgrades all routers owned by the specified account")
+    private Long accountId;
+
+    @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType=DomainResponse.class,
+            description="upgrades all routers owned by the specified domain")
+    private Long domainId;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getId() {
+        return id;
+    }
+
+    public Long getClusterId() {
+        return clusterId;
+    }
+
+    public Long getPodId() {
+        return podId;
+    }
+
+    public Long getZoneId() {
+        return zoneId;
+    }
+
+    public Long getAccountId() {
+        return accountId;
+    }
+
+    public Long getDomainId() {
+        return domainId;
+    }
+
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+    }
+
+    public ApiCommandJobType getInstanceType() {
+        return ApiCommandJobType.DomainRouter;
+    }
+
+    public Long getInstanceId() {
+        return getId();
+    }
+
+    @Override
+    public void execute() throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
+        CallContext.current().setEventDetails("Upgrading router template");
+        List<Long> result = _routerService.upgradeRouterTemplate(this);
+        if (result != null){
+            ListResponse<UpgradeRouterTemplateResponse> response = _responseGenerator.createUpgradeRouterTemplateResponse(result);
+            response.setResponseName(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to upgrade router template");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3f5b8f70/api/src/org/apache/cloudstack/api/response/DomainRouterResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/DomainRouterResponse.java b/api/src/org/apache/cloudstack/api/response/DomainRouterResponse.java
index 1d31b58..5ea28b9 100644
--- a/api/src/org/apache/cloudstack/api/response/DomainRouterResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/DomainRouterResponse.java
@@ -144,8 +144,8 @@ public class DomainRouterResponse extends BaseResponse implements ControlledView
     @SerializedName("redundantstate") @Param(description="the state of redundant virtual router")
     private String redundantState;
 
-    @SerializedName("templateversion") @Param(description="the version of template")
-    private String templateVersion;
+    @SerializedName("version") @Param(description="the version of template")
+    private String version;
 
     @SerializedName("scriptsversion") @Param(description="the version of scripts")
     private String scriptsVersion;
@@ -160,6 +160,9 @@ public class DomainRouterResponse extends BaseResponse implements ControlledView
             responseObject = NicResponse.class, since="4.0")
     private Set<NicResponse> nics;
 
+    @SerializedName("requiresupgrade") @Param(description="true if the router template requires upgrader")
+    private boolean requiresUpgrade;
+
     public DomainRouterResponse(){
         nics = new LinkedHashSet<NicResponse>();
     }
@@ -308,12 +311,12 @@ public class DomainRouterResponse extends BaseResponse implements ControlledView
         this.isRedundantRouter = isRedundantRouter;
     }
 
-    public String getTemplateVersion() {
-        return this.templateVersion;
+    public String getVersion() {
+        return this.version;
     }
 
-    public void setTemplateVersion(String templateVersion) {
-        this.templateVersion = templateVersion;
+    public void setVersion(String version) {
+        this.version = version;
     }
 
     public String getScriptsVersion() {
@@ -364,4 +367,12 @@ public class DomainRouterResponse extends BaseResponse implements ControlledView
 	public void setRole(String role) {
         this.role = role;
     }
+
+    public boolean requiresUpgrade() {
+        return requiresUpgrade;
+    }
+
+    public void setRequiresUpgrade(boolean requiresUpgrade) {
+        this.requiresUpgrade = requiresUpgrade;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3f5b8f70/api/src/org/apache/cloudstack/api/response/UpgradeRouterTemplateResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/UpgradeRouterTemplateResponse.java b/api/src/org/apache/cloudstack/api/response/UpgradeRouterTemplateResponse.java
new file mode 100644
index 0000000..ba0049b
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/response/UpgradeRouterTemplateResponse.java
@@ -0,0 +1,45 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.response;
+
+import com.cloud.serializer.Param;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachine.State;
+import com.google.gson.annotations.SerializedName;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.api.EntityReference;
+import org.apache.cloudstack.jobs.JobInfo;
+
+import java.util.Date;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+@EntityReference(value = JobInfo.class)
+@SuppressWarnings("unused")
+public class UpgradeRouterTemplateResponse extends BaseResponse {
+    @SerializedName(ApiConstants.JOB_ID) @Param(description="the id of AsyncJob")
+    private String asyncJobId;
+
+    public String getAsyncJobId() {
+        return asyncJobId;
+    }
+
+    public void setAsyncJobId(String asyncJobId) {
+        this.asyncJobId = asyncJobId;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3f5b8f70/client/tomcatconf/commands.properties.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index 087d8b9..68d7303 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -197,6 +197,7 @@ listRouters=7
 listVirtualRouterElements=7
 configureVirtualRouterElement=7
 createVirtualRouterElement=7
+upgradeRouterTemplate=1
 
 #### system vm commands
 startSystemVm=1

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3f5b8f70/engine/schema/src/com/cloud/vm/dao/DomainRouterDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/vm/dao/DomainRouterDao.java b/engine/schema/src/com/cloud/vm/dao/DomainRouterDao.java
index 95d1ea6..f1912b5 100755
--- a/engine/schema/src/com/cloud/vm/dao/DomainRouterDao.java
+++ b/engine/schema/src/com/cloud/vm/dao/DomainRouterDao.java
@@ -145,5 +145,6 @@ public interface DomainRouterDao extends GenericDao<DomainRouterVO, Long> {
      * @param guestNetworkId
      */
     void removeRouterFromGuestNetwork(long routerId, long guestNetworkId);
-    
+
+    List<DomainRouterVO> listByClusterId(Long clusterId);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3f5b8f70/engine/schema/src/com/cloud/vm/dao/DomainRouterDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/vm/dao/DomainRouterDaoImpl.java b/engine/schema/src/com/cloud/vm/dao/DomainRouterDaoImpl.java
index 7676e2d..5158e98 100755
--- a/engine/schema/src/com/cloud/vm/dao/DomainRouterDaoImpl.java
+++ b/engine/schema/src/com/cloud/vm/dao/DomainRouterDaoImpl.java
@@ -204,6 +204,13 @@ public class DomainRouterDaoImpl extends GenericDaoBase<DomainRouterVO, Long> im
     }
 
     @Override
+    public List<DomainRouterVO> listByClusterId(Long clusterId) {
+        SearchCriteria<DomainRouterVO> sc = AllFieldsSearch.create();
+        //ToDo: Add cluster criteria
+        return listBy(sc);
+    }
+
+    @Override
     public List<DomainRouterVO> listByPodIdAndStates(Long podId, State... states) {
         SearchCriteria<DomainRouterVO> sc = AllFieldsSearch.create();
         sc.setParameters("podId", podId);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3f5b8f70/server/src/com/cloud/api/ApiResponseHelper.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java
index 36ef4bd..e1c48cf 100755
--- a/server/src/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/com/cloud/api/ApiResponseHelper.java
@@ -79,6 +79,7 @@ import org.apache.cloudstack.api.response.LBHealthCheckPolicyResponse;
 import org.apache.cloudstack.api.response.LBHealthCheckResponse;
 import org.apache.cloudstack.api.response.LBStickinessPolicyResponse;
 import org.apache.cloudstack.api.response.LBStickinessResponse;
+import org.apache.cloudstack.api.response.ListResponse;
 import org.apache.cloudstack.api.response.LoadBalancerResponse;
 import org.apache.cloudstack.api.response.NetworkACLItemResponse;
 import org.apache.cloudstack.api.response.NetworkACLResponse;
@@ -119,6 +120,7 @@ import org.apache.cloudstack.api.response.TemplatePermissionsResponse;
 import org.apache.cloudstack.api.response.TemplateResponse;
 import org.apache.cloudstack.api.response.TrafficMonitorResponse;
 import org.apache.cloudstack.api.response.TrafficTypeResponse;
+import org.apache.cloudstack.api.response.UpgradeRouterTemplateResponse;
 import org.apache.cloudstack.api.response.UsageRecordResponse;
 import org.apache.cloudstack.api.response.UserResponse;
 import org.apache.cloudstack.api.response.UserVmResponse;
@@ -3793,4 +3795,19 @@ public class ApiResponseHelper implements ResponseGenerator {
         response.setObjectName("networkacllist");
         return response;
     }
+
+    @Override
+    public ListResponse<UpgradeRouterTemplateResponse> createUpgradeRouterTemplateResponse(List<Long> jobIds){
+        ListResponse<UpgradeRouterTemplateResponse> response = new ListResponse<UpgradeRouterTemplateResponse>();
+        List<UpgradeRouterTemplateResponse> responses = new ArrayList<UpgradeRouterTemplateResponse>();
+        for(Long jobId : jobIds){
+            UpgradeRouterTemplateResponse routerResponse = new UpgradeRouterTemplateResponse();
+            AsyncJob job = _entityMgr.findById(AsyncJob.class, jobId);
+            routerResponse.setAsyncJobId((job.getUuid()));
+            routerResponse.setObjectName("asyncjobs");
+            responses.add(routerResponse);
+        }
+        response.setResponses(responses);
+        return response;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3f5b8f70/server/src/com/cloud/api/query/QueryManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java
index 2934641..2b5b81d 100644
--- a/server/src/com/cloud/api/query/QueryManagerImpl.java
+++ b/server/src/com/cloud/api/query/QueryManagerImpl.java
@@ -1090,7 +1090,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
     public ListResponse<DomainRouterResponse> searchForRouters(ListRoutersCmd cmd) {
         Pair<List<DomainRouterJoinVO>, Integer> result = searchForRoutersInternal(cmd, cmd.getId(), cmd.getRouterName(),
                 cmd.getState(), cmd.getZoneId(), cmd.getPodId(), cmd.getHostId(), cmd.getKeyword(), cmd.getNetworkId(),
-                cmd.getVpcId(), cmd.getForVpc(), cmd.getRole());
+                cmd.getVpcId(), cmd.getForVpc(), cmd.getRole(), cmd.getVersion());
         ListResponse<DomainRouterResponse> response = new ListResponse<DomainRouterResponse>();
 
         List<DomainRouterResponse> routerResponses = ViewResponseHelper.createDomainRouterResponse(result.first()
@@ -1103,7 +1103,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
     public ListResponse<DomainRouterResponse> searchForInternalLbVms(ListInternalLBVMsCmd cmd) {
         Pair<List<DomainRouterJoinVO>, Integer> result = searchForRoutersInternal(cmd, cmd.getId(), cmd.getRouterName(),
                 cmd.getState(), cmd.getZoneId(), cmd.getPodId(), cmd.getHostId(), cmd.getKeyword(), cmd.getNetworkId(),
-                cmd.getVpcId(), cmd.getForVpc(), cmd.getRole());
+                cmd.getVpcId(), cmd.getForVpc(), cmd.getRole(), null);
         ListResponse<DomainRouterResponse> response = new ListResponse<DomainRouterResponse>();
 
         List<DomainRouterResponse> routerResponses = ViewResponseHelper.createDomainRouterResponse(result.first()
@@ -1113,7 +1113,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
     }
 
     private Pair<List<DomainRouterJoinVO>, Integer> searchForRoutersInternal(BaseListProjectAndAccountResourcesCmd cmd, Long id,
-            String name, String state, Long zoneId, Long podId, Long hostId, String keyword, Long networkId, Long vpcId, Boolean forVpc, String role) {
+            String name, String state, Long zoneId, Long podId, Long hostId, String keyword, Long networkId, Long vpcId, Boolean forVpc,
+            String role, String version) {
 
         Account caller = CallContext.current().getCallingAccount();
         List<Long> permittedAccounts = new ArrayList<Long>();
@@ -1147,6 +1148,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
         sb.and("hostId", sb.entity().getHostId(), SearchCriteria.Op.EQ);
         sb.and("vpcId", sb.entity().getVpcId(), SearchCriteria.Op.EQ);
         sb.and("role", sb.entity().getRole(), SearchCriteria.Op.EQ);
+        sb.and("version", sb.entity().getTemplateVersion(), SearchCriteria.Op.EQ);
 
         if (forVpc != null) {
             if (forVpc) {
@@ -1210,6 +1212,10 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
             sc.setParameters("role", role);
         }
 
+        if(version != null){
+            sc.setParameters("version", "Cloudstack Release "+version + "%");
+        }
+
         // search VR details by ids
         Pair<List<DomainRouterJoinVO>, Integer> uniqueVrPair = _routerJoinDao.searchAndCount(sc, searchFilter);
         Integer count = uniqueVrPair.second();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3f5b8f70/server/src/com/cloud/api/query/ViewResponseHelper.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/ViewResponseHelper.java b/server/src/com/cloud/api/query/ViewResponseHelper.java
index 4051f09..e4be311 100644
--- a/server/src/com/cloud/api/query/ViewResponseHelper.java
+++ b/server/src/com/cloud/api/query/ViewResponseHelper.java
@@ -58,6 +58,7 @@ import org.apache.cloudstack.api.response.SecurityGroupResponse;
 import org.apache.cloudstack.api.response.ServiceOfferingResponse;
 import org.apache.cloudstack.api.response.StoragePoolResponse;
 import org.apache.cloudstack.api.response.TemplateResponse;
+import org.apache.cloudstack.api.response.UpgradeRouterTemplateResponse;
 import org.apache.cloudstack.api.response.UserResponse;
 import org.apache.cloudstack.api.response.UserVmResponse;
 import org.apache.cloudstack.api.response.VolumeResponse;
@@ -440,4 +441,5 @@ public class ViewResponseHelper {
         }
         return new ArrayList<AffinityGroupResponse>(vrDataList.values());
     }
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3f5b8f70/server/src/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java
index 42965bc..f193031 100644
--- a/server/src/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java
@@ -22,6 +22,8 @@ import java.util.List;
 import javax.ejb.Local;
 import javax.inject.Inject;
 
+import com.cloud.maint.Version;
+import com.cloud.network.VirtualNetworkApplianceService;
 import org.apache.cloudstack.api.response.DomainRouterResponse;
 import org.apache.cloudstack.api.response.NicResponse;
 import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
@@ -76,6 +78,11 @@ public class DomainRouterJoinDaoImpl extends GenericDaoBase<DomainRouterJoinVO,
         routerResponse.setState(router.getState());
         routerResponse.setIsRedundantRouter(router.isRedundantRouter());
         routerResponse.setRedundantState(router.getRedundantState().toString());
+        if(router.getTemplateVersion() != null){
+            String routerVersion = Version.trimRouterVersion(router.getTemplateVersion());
+            routerResponse.setVersion(routerVersion);
+            routerResponse.setRequiresUpgrade((Version.compare(routerVersion, VirtualNetworkApplianceService._minVRVersion) < 0));
+        }
 
         if (caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN
                 || caller.getType() == Account.ACCOUNT_TYPE_ADMIN) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3f5b8f70/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
index 0f7c5c9..617d6ac 100755
--- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
+++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
@@ -30,6 +30,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TimeZone;
+import java.util.UUID;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -42,14 +43,23 @@ import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
 import com.cloud.agent.api.to.*;
+import com.cloud.api.ApiAsyncJobDispatcher;
+import com.cloud.api.ApiDispatcher;
+import com.cloud.api.ApiGsonHelper;
+import com.cloud.maint.Version;
+import com.cloud.utils.component.ComponentContext;
+import org.apache.cloudstack.api.command.admin.router.RebootRouterCmd;
 import org.apache.cloudstack.api.command.admin.router.UpgradeRouterCmd;
 import org.apache.cloudstack.context.CallContext;
 import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
 import org.apache.cloudstack.framework.config.ConfigDepot;
 import org.apache.cloudstack.framework.config.ConfigKey;
 import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.framework.jobs.AsyncJobManager;
+import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
 import org.apache.cloudstack.managed.context.ManagedContextRunnable;
 import org.apache.cloudstack.utils.identity.ManagementServerNode;
+import org.apache.cloudstack.api.command.admin.router.UpgradeRouterTemplateCmd;
 import org.apache.log4j.Logger;
 
 import com.cloud.agent.AgentManager;
@@ -370,8 +380,10 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
     ConfigDepot _configDepot;
     @Inject
     MonitoringServiceDao _monitorServiceDao;
-
-
+    @Inject
+    AsyncJobManager _asyncMgr;
+    @Inject
+    protected ApiAsyncJobDispatcher _asyncDispatcher;
 
     int _routerRamSize;
     int _routerCpuMHz;
@@ -3551,6 +3563,9 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
     }
 
     protected boolean sendCommandsToRouter(final VirtualRouter router, Commands cmds) throws AgentUnavailableException {
+        if(!checkRouterVersion(router)){
+            throw new CloudRuntimeException("Router requires upgrade. Unable to send command to router:" + router.getId());
+        }
         Answer[] answers = null;
         try {
             answers = _agentMgr.send(router.getHostId(), cmds);
@@ -4119,4 +4134,94 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
     public VirtualRouter findRouter(long routerId) {
         return _routerDao.findById(routerId);
     }
+
+    @Override
+    public List<Long> upgradeRouterTemplate(UpgradeRouterTemplateCmd cmd){
+
+        List<DomainRouterVO> routers = new ArrayList<DomainRouterVO>();
+        int params = 0;
+
+        Long routerId = cmd.getId();
+        if(routerId != null)    {
+            params++;
+            DomainRouterVO router = _routerDao.findById(routerId);
+            if(router != null){
+                routers.add(router);
+            }
+        }
+
+        Long accountId = cmd.getAccountId();
+        if(accountId != null){
+            params++;
+            routers = _routerDao.listBy(accountId);
+        }
+
+        Long domainId = cmd.getDomainId();
+        if(domainId != null){
+            params++;
+            routers = _routerDao.listByDomain(domainId);
+        }
+
+        Long clusterId = cmd.getClusterId();
+        if(clusterId != null){
+            params++;
+            routers = _routerDao.listByClusterId(clusterId);
+        }
+
+        Long podId = cmd.getPodId();
+        if(podId != null){
+            params++;
+            routers = _routerDao.listByPodId(podId);
+        }
+
+        Long zoneId = cmd.getZoneId();
+        if(zoneId != null){
+            params++;
+            routers = _routerDao.listByDataCenter(zoneId);
+        }
+
+        if(params > 1){
+            throw new InvalidParameterValueException("Multiple parameters not supported. Specify only one among routerId/zoneId/podId/clusterId/accountId/domainId");
+        }
+
+        if(routers != null){
+            return rebootRouters(routers);
+        }
+
+        return null;
+    }
+
+    //Checks if the router is at the required version
+    // Compares MS version and router version
+    private boolean checkRouterVersion(VirtualRouter router){
+        String trimmedVersion = Version.trimRouterVersion(router.getTemplateVersion());
+        return (Version.compare(trimmedVersion, _minVRVersion) >= 0);
+    }
+
+    private List<Long> rebootRouters(List<DomainRouterVO> routers){
+        List<Long> jobIds = new ArrayList<Long>();
+        for(DomainRouterVO router: routers){
+            if(!checkRouterVersion(router)){
+                    s_logger.debug("Upgrading template for router: "+router.getId());
+                    ApiDispatcher.getInstance();
+                    Map<String, String> params = new HashMap<String, String>();
+                    params.put("ctxUserId", "1");
+                    params.put("ctxAccountId", "" + router.getAccountId());
+
+                    RebootRouterCmd cmd = new RebootRouterCmd();
+                    ComponentContext.inject(cmd);
+                    params.put("id", ""+router.getId());
+                    params.put("ctxStartEventId", "1");
+                    AsyncJobVO job = new AsyncJobVO(UUID.randomUUID().toString(), User.UID_SYSTEM, router.getAccountId(), RebootRouterCmd.class.getName(),
+                            ApiGsonHelper.getBuilder().create().toJson(params), router.getId(),
+                            cmd.getInstanceType() != null ? cmd.getInstanceType().toString() : null);
+                    job.setDispatcher(_asyncDispatcher.getName());
+                    long jobId = _asyncMgr.submitAsyncJob(job);
+                    jobIds.add(jobId);
+            } else {
+                s_logger.debug("Router: "+router.getId()+" is already at the latest version. No upgrade required" );
+            }
+        }
+        return jobIds;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3f5b8f70/server/src/com/cloud/server/ManagementServerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java
index 79b20d0..35bc681 100755
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -42,6 +42,7 @@ import javax.crypto.spec.SecretKeySpec;
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
+import org.apache.cloudstack.api.command.admin.router.UpgradeRouterTemplateCmd;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.log4j.Logger;
 
@@ -2874,6 +2875,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
         cmdList.add(ReplaceNetworkACLListCmd.class);
         cmdList.add(UpdateNetworkACLItemCmd.class);
         cmdList.add(CleanVMReservationsCmd.class);
+        cmdList.add(UpgradeRouterTemplateCmd.class);
         return cmdList;
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3f5b8f70/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java b/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java
index acdd9dc..5c216c8 100644
--- a/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java
+++ b/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java
@@ -24,7 +24,7 @@ import javax.ejb.Local;
 import javax.naming.ConfigurationException;
 
 import com.cloud.network.vpc.NetworkACLItem;
-import org.apache.cloudstack.api.command.admin.router.UpgradeRouterCmd;
+import org.apache.cloudstack.api.command.admin.router.*;
 import org.springframework.stereotype.Component;
 
 import com.cloud.deploy.DeployDestination;
@@ -421,6 +421,11 @@ VpcVirtualNetworkApplianceService {
     }
 
     @Override
+    public List<Long> upgradeRouterTemplate(UpgradeRouterTemplateCmd cmd) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
     public boolean setupDhcpForPvlan(boolean add, DomainRouterVO router, Long hostId,
             NicProfile nic) {
         // TODO Auto-generated method stub

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3f5b8f70/utils/src/com/cloud/maint/Version.java
----------------------------------------------------------------------
diff --git a/utils/src/com/cloud/maint/Version.java b/utils/src/com/cloud/maint/Version.java
index 7317547..f900b56 100644
--- a/utils/src/com/cloud/maint/Version.java
+++ b/utils/src/com/cloud/maint/Version.java
@@ -58,6 +58,14 @@ public class Version {
         	return "0";
         return tokens[0] + "." + tokens[1]+ "." + tokens[2];
     }
+
+    public static String trimRouterVersion(String version){
+        String[] tokens = version.split(" ");
+        if(tokens.length >= 3){
+            return tokens[2];
+        }
+        return "0";
+    }
     
     public static void main(String[] args) {
     	System.out.println("Result is " + compare(args[0], args[1]));