Updated Branches: refs/heads/4.3 3b59dfebf -> ef6038f1b
commit 8edaf63c4e4a054b17a2dfe4233d103fb2ee9e6a Author: Frank.Zhang <frank.zh...@citrix.com> Date: Thu Oct 10 14:45:03 2013 -0700 CLOUDSTACK-4850 [UCS] using template instead of cloning profile Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/ef6038f1 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/ef6038f1 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/ef6038f1 Branch: refs/heads/4.3 Commit: ef6038f1b3fc8bcf64c54d38c0b53f0cd47d2ded Parents: 3b59dfe Author: Frank.Zhang <frank.zh...@citrix.com> Authored: Thu Dec 5 17:25:57 2013 -0800 Committer: Frank.Zhang <frank.zh...@citrix.com> Committed: Thu Dec 5 17:25:57 2013 -0800 ---------------------------------------------------------------------- api/src/com/cloud/event/EventTypes.java | 3 + .../org/apache/cloudstack/api/ApiConstants.java | 3 + client/tomcatconf/commands.properties.in | 4 + plugins/hypervisors/ucs/pom.xml | 46 +++- .../com/cloud/ucs/database/UcsBladeDaoImpl.java | 2 + .../com/cloud/ucs/database/UcsManagerDao.java | 1 - .../cloud/ucs/database/UcsManagerDaoImpl.java | 2 + .../src/com/cloud/ucs/manager/UcsCommands.java | 108 +++++--- .../com/cloud/ucs/manager/UcsHttpClient.java | 66 ++++- .../src/com/cloud/ucs/manager/UcsManager.java | 19 +- .../com/cloud/ucs/manager/UcsManagerImpl.java | 264 ++++++++++++++----- 11 files changed, 393 insertions(+), 125 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ef6038f1/api/src/com/cloud/event/EventTypes.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index f3fb879..77d2fab 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -452,6 +452,9 @@ public class EventTypes { public static final String EVENT_CLEANUP_VM_RESERVATION = "VM.RESERVATION.CLEANUP"; public static final String EVENT_UCS_ASSOCIATED_PROFILE = "UCS.ASSOCIATEPROFILE"; + public static final String EVENT_UCS_INSTANTIATE_TEMPLATE_AND_ASSOCIATE = "UCS.TEMPLATEASSOCIATION"; + public static final String EVENT_UCS_DISASSOCIATED_PROFILE = "UCS.DISASSOCIATEPROFILE"; + public static final String EVENT_UCS_REFRESH_BLADES = "UCS.REFRESHBLADES"; // Object store migration public static final String EVENT_MIGRATE_PREPARE_SECONDARY_STORAGE = "MIGRATE.PREPARE.SS"; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ef6038f1/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 acb1423..cd8379b 100755 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -506,8 +506,11 @@ public class ApiConstants { public static final String RESERVED_IP_RANGE = "reservediprange"; public static final String UCS_MANAGER_ID = "ucsmanagerid"; public static final String UCS_PROFILE_DN = "profiledn"; + public static final String UCS_TEMPLATE_DN = "templatedn"; public static final String UCS_BLADE_DN = "bladedn"; public static final String UCS_BLADE_ID = "bladeid"; + public static final String UCS_PROFILE_NAME = "profilename"; + public static final String UCS_DELETE_PROFILE = "deleteprofile"; public static final String VM_GUEST_IP = "vmguestip"; public static final String HEALTHCHECK_RESPONSE_TIMEOUT = "responsetimeout"; public static final String HEALTHCHECK_INTERVAL_TIME = "intervaltime"; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ef6038f1/client/tomcatconf/commands.properties.in ---------------------------------------------------------------------- diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 60258a0..773c035 100644 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -637,8 +637,12 @@ addUcsManager=1 listUcsManagers=1 listUcsProfiles=1 listUcsBlades=1 +listUcsTemplates=1 associateUcsProfileToBlade=1 deleteUcsManager=1 +disassociateUcsProfileFromBlade=1 +refreshUcsBlades=1 +instantiateUcsTemplateAndAssocaciateToBlade=1 #### New Load Balancer commands createLoadBalancer=15 http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ef6038f1/plugins/hypervisors/ucs/pom.xml ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ucs/pom.xml b/plugins/hypervisors/ucs/pom.xml index ae9708c..11732ab 100755 --- a/plugins/hypervisors/ucs/pom.xml +++ b/plugins/hypervisors/ucs/pom.xml @@ -1,16 +1,25 @@ -<!-- 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. --> -<project - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 +<!-- + 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. +--> +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" - xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.apache.cloudstack</groupId> @@ -18,7 +27,9 @@ <version>4.3.0-SNAPSHOT</version> <relativePath>../../pom.xml</relativePath> </parent> + <groupId>org.apache.cloudstack</groupId> <artifactId>cloud-plugin-hypervisor-ucs</artifactId> + <version>4.3.0-SNAPSHOT</version> <name>Apache CloudStack Plugin - Hypervisor UCS</name> <url>http://maven.apache.org</url> <properties> @@ -26,6 +37,12 @@ </properties> <dependencies> <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>3.8.1</version> + <scope>test</scope> + </dependency> + <dependency> <groupId>org.apache.cloudstack</groupId> <artifactId>cloud-utils</artifactId> <version>${project.version}</version> @@ -35,5 +52,10 @@ <artifactId>cloud-api</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>javax.inject</groupId> + <artifactId>javax.inject</artifactId> + <version>1</version> + </dependency> </dependencies> </project> http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ef6038f1/plugins/hypervisors/ucs/src/com/cloud/ucs/database/UcsBladeDaoImpl.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ucs/src/com/cloud/ucs/database/UcsBladeDaoImpl.java b/plugins/hypervisors/ucs/src/com/cloud/ucs/database/UcsBladeDaoImpl.java index 5dc6f79..9853194 100644 --- a/plugins/hypervisors/ucs/src/com/cloud/ucs/database/UcsBladeDaoImpl.java +++ b/plugins/hypervisors/ucs/src/com/cloud/ucs/database/UcsBladeDaoImpl.java @@ -19,6 +19,8 @@ package com.cloud.ucs.database; import javax.ejb.Local; +import org.springframework.stereotype.Component; + import com.cloud.utils.db.DB; import com.cloud.utils.db.GenericDaoBase; @Local(value = { UcsBladeDao.class }) http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ef6038f1/plugins/hypervisors/ucs/src/com/cloud/ucs/database/UcsManagerDao.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ucs/src/com/cloud/ucs/database/UcsManagerDao.java b/plugins/hypervisors/ucs/src/com/cloud/ucs/database/UcsManagerDao.java index b341a1b..9ae4e77 100644 --- a/plugins/hypervisors/ucs/src/com/cloud/ucs/database/UcsManagerDao.java +++ b/plugins/hypervisors/ucs/src/com/cloud/ucs/database/UcsManagerDao.java @@ -27,7 +27,6 @@ import com.cloud.utils.db.GenericDao; import com.cloud.utils.db.GenericSearchBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; -import com.cloud.utils.db.GenericQueryBuilder; public interface UcsManagerDao extends GenericDao<UcsManagerVO, Long> { } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ef6038f1/plugins/hypervisors/ucs/src/com/cloud/ucs/database/UcsManagerDaoImpl.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ucs/src/com/cloud/ucs/database/UcsManagerDaoImpl.java b/plugins/hypervisors/ucs/src/com/cloud/ucs/database/UcsManagerDaoImpl.java index 9500886..3091978 100644 --- a/plugins/hypervisors/ucs/src/com/cloud/ucs/database/UcsManagerDaoImpl.java +++ b/plugins/hypervisors/ucs/src/com/cloud/ucs/database/UcsManagerDaoImpl.java @@ -19,6 +19,8 @@ package com.cloud.ucs.database; import javax.ejb.Local; +import org.springframework.stereotype.Component; + import com.cloud.utils.db.DB; import com.cloud.utils.db.GenericDaoBase; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ef6038f1/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsCommands.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsCommands.java b/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsCommands.java index c0753f4..8232844 100644 --- a/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsCommands.java +++ b/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsCommands.java @@ -50,6 +50,27 @@ public class UcsCommands { return cmd.dump(); } + public static String listTemplates(String cookie) { + XmlObject cmd = new XmlObject("configResolveClass"); + cmd.putElement("cookie", cookie); + cmd.putElement("inHierarchical", "false"); + cmd.putElement("classId", "lsServer"); + cmd.putElement("inFilter", new XmlObject("inFilter") + .putElement("eq", new XmlObject("eq") + .putElement("class", "lsServer").putElement("property", "type").putElement("value", "initial-template"))); + return cmd.dump(); + } + + public static String instantiateTemplate(String cookie, String dn, String name) { + XmlObject cmd = new XmlObject("lsInstantiateTemplate"); + cmd.putElement("dn",dn); + cmd.putElement("cookie", cookie); + cmd.putElement("inTargetOrg", "org-root"); + cmd.putElement("inServerName", name); + cmd.putElement("inHierarchical", "no"); + return cmd.toString(); + } + public static String cloneProfile(String cookie, String srcDn, String newProfileName) { XmlObject cmd = new XmlObject("lsClone"); cmd.putElement("cookie", cookie); @@ -67,41 +88,64 @@ public class UcsCommands { return cmd.toString(); } + public static String disassociateProfileFromBlade(String cookie, String profileDn) { + XmlObject cmd = new XmlObject("configConfMo"); + cmd.putElement("cookie", cookie); + cmd.putElement("inHierarchical", "false") + .putElement("inConfig", new XmlObject("inConfig") + .putElement("lsServer", new XmlObject("lsServer") + .putElement("dn", profileDn).putElement("lsBinding", new XmlObject("lsBinding").putElement("rn", "pn").putElement("status", "deleted")) + ) + ); + + return cmd.dump(); + } + + public static String deleteProfile(String cookie, String profileDn) { + XmlObject cmd = new XmlObject("configConfMos"); + cmd.putElement("cookie", cookie); + cmd.putElement("inHierarchical", "true") + .putElement("inConfigs", new XmlObject("inConfigs").putElement("pair", new XmlObject("pair").putElement("key", profileDn) + .putElement("lsServer", new XmlObject("lsServer").putElement("dn", profileDn).putElement("status", "deleted")) + )); + return cmd.dump(); + } + public static String associateProfileToBlade(String cookie, String profileDn, String bladeDn) { XmlObject cmd = new XmlObject("configConfMos").putElement("cookie", cookie).putElement("inHierarchical", "true").putElement( "inConfigs", new XmlObject("inConfigs").putElement( - "pair", new XmlObject("pair").putElement("key", profileDn).putElement( - "lsServer", new XmlObject("lsServer") - .putElement("agentPolicyName", "") - .putElement("biosProfileName", "") - .putElement("bootPolicyName", "") - .putElement("descr", "") - .putElement("dn", profileDn) - .putElement("dynamicConPolicyName", "") - .putElement("extIPState", "none") - .putElement("hostFwPolicyName", "") - .putElement("identPoolName", "") - .putElement("localDiskPolicyName", "") - .putElement("maintPolicyName", "") - .putElement("mgmtAccessPolicyName", "") - .putElement("mgmtFwPolicyName", "") - .putElement("powerPolicyName", "") - .putElement("scrubPolicyName", "") - .putElement("solPolicyName", "") - .putElement("srcTemplName", "") - .putElement("statsPolicyName", "default") - .putElement("status", "") - .putElement("usrLbl", "") - .putElement("uuid", "") - .putElement("vconProfileName", "") - .putElement("lsBinding", new XmlObject("lsBinding") - .putElement("pnDn", bladeDn) - .putElement("restrictMigration", "no") - .putElement("rn", "pn") - ) - ) - ) - ); + "pair", new XmlObject("pair").putElement("key", profileDn).putElement( + "lsServer", new XmlObject("lsServer") + .putElement("agentPolicyName", "") + .putElement("biosProfileName", "") + .putElement("bootPolicyName", "") + .putElement("descr", "") + .putElement("dn", profileDn) + .putElement("dynamicConPolicyName", "") + .putElement("extIPState", "none") + .putElement("hostFwPolicyName", "") + .putElement("identPoolName", "") + .putElement("localDiskPolicyName", "") + .putElement("maintPolicyName", "") + .putElement("mgmtAccessPolicyName", "") + .putElement("mgmtFwPolicyName", "") + .putElement("powerPolicyName", "") + .putElement("scrubPolicyName", "") + .putElement("solPolicyName", "") + .putElement("srcTemplName", "") + .putElement("statsPolicyName", "default") + .putElement("status", "") + .putElement("usrLbl", "") + .putElement("uuid", "") + .putElement("vconProfileName", "") + .putElement("lsBinding", new XmlObject("lsBinding") + .putElement("pnDn", bladeDn) + .putElement("restrictMigration", "no") + .putElement("rn", "pn") + ) + ) + ) + ); return cmd.dump(); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ef6038f1/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsHttpClient.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsHttpClient.java b/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsHttpClient.java index 945d921..1eb422c 100644 --- a/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsHttpClient.java +++ b/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsHttpClient.java @@ -17,27 +17,76 @@ // package com.cloud.ucs.manager; -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.URI; +import com.cloud.utils.exception.CloudRuntimeException; import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory; -import org.apache.commons.httpclient.methods.PostMethod; -import org.apache.commons.httpclient.methods.StringRequestEntity; import org.apache.commons.httpclient.protocol.Protocol; +import org.apache.log4j.Logger; +import org.springframework.http.*; +import org.springframework.web.client.RestTemplate; -import com.cloud.utils.exception.CloudRuntimeException; +import java.net.URI; +import java.net.URISyntaxException; public class UcsHttpClient { - private static HttpClient client = new HttpClient(); + private static final Logger logger = Logger.getLogger(UcsHttpClient.class); + //private static HttpClient client; private static Protocol ucsHttpsProtocol = new org.apache.commons.httpclient.protocol.Protocol("https", new EasySSLProtocolSocketFactory(), 443); private final String url; + private static RestTemplate template; + + static { + //client = new HttpClient(); + template = new RestTemplate(); + } public UcsHttpClient(String ip) { url = String.format("http://%s/nuova", ip); Protocol.registerProtocol("https", ucsHttpsProtocol); } - public String call(String xml) { + + private String call(URI uri, String body) { + HttpHeaders requestHeaders = new HttpHeaders(); + requestHeaders.setContentType(MediaType.APPLICATION_XML); + requestHeaders.setContentLength(body.length()); + HttpEntity<String> req = new HttpEntity<String>(body, requestHeaders); + if (!body.contains("aaaLogin")) { + logger.debug(String.format("UCS call: %s", body)); + } + ResponseEntity<String> rsp = template.exchange(uri, HttpMethod.POST, req, String.class); + if (rsp.getStatusCode() == org.springframework.http.HttpStatus.OK) { + return rsp.getBody(); + } else if (rsp.getStatusCode() == org.springframework.http.HttpStatus.FOUND) { + // Handle HTTPS redirect + // Ideal way might be to configure from add manager API + // for using either HTTP / HTTPS + // Allow only one level of redirect + java.net.URI location = rsp.getHeaders().getLocation(); + if (location == null) { + throw new CloudRuntimeException("Call failed: Bad redirect from UCS Manager"); + } + //call(location, body); + rsp = template.exchange(location, HttpMethod.POST, req, String.class); + } + if (rsp.getStatusCode() != org.springframework.http.HttpStatus.OK) { + String err = String.format("http status: %s, response body:%s", rsp.getStatusCode().toString(), rsp.getBody()); + throw new CloudRuntimeException(String.format("UCS API call failed, details: %s\n", err)); + } + + if (rsp.getBody().contains("errorCode")) { + String err = String.format("ucs call failed:\nsubmitted doc:%s\nresponse:%s\n", body, rsp.getBody()); + throw new CloudRuntimeException(err); + } + return rsp.getBody(); + } + + public String call(String body) { + try { + return call(new URI(url), body); + } catch (URISyntaxException e) { + throw new CloudRuntimeException(e); + } + /* PostMethod post = new PostMethod(url); post.setRequestEntity(new StringRequestEntity(xml)); post.setRequestHeader("Content-type", "text/xml"); @@ -75,5 +124,6 @@ public class UcsHttpClient { } finally { post.releaseConnection(); } + */ } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ef6038f1/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManager.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManager.java b/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManager.java index 0833e31..0cd695c 100755 --- a/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManager.java +++ b/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManager.java @@ -17,15 +17,8 @@ // package com.cloud.ucs.manager; -import org.apache.cloudstack.api.AddUcsManagerCmd; -import org.apache.cloudstack.api.AssociateUcsProfileToBladeCmd; -import org.apache.cloudstack.api.ListUcsBladeCmd; -import org.apache.cloudstack.api.ListUcsManagerCmd; -import org.apache.cloudstack.api.ListUcsProfileCmd; -import org.apache.cloudstack.api.response.ListResponse; -import org.apache.cloudstack.api.response.UcsBladeResponse; -import org.apache.cloudstack.api.response.UcsManagerResponse; -import org.apache.cloudstack.api.response.UcsProfileResponse; +import org.apache.cloudstack.api.*; +import org.apache.cloudstack.api.response.*; import com.cloud.utils.component.Manager; import com.cloud.utils.component.PluggableService; @@ -35,11 +28,19 @@ public interface UcsManager extends Manager, PluggableService { ListResponse<UcsProfileResponse> listUcsProfiles(ListUcsProfileCmd cmd); + ListResponse<UcsTemplateResponse> listUcsTemplates(ListUcsTemplatesCmd cmd); + ListResponse<UcsManagerResponse> listUcsManager(ListUcsManagerCmd cmd); UcsBladeResponse associateProfileToBlade(AssociateUcsProfileToBladeCmd cmd); + UcsBladeResponse instantiateTemplateAndAssociateToBlade(InstantiateUcsTemplateAndAssociateToBladeCmd cmd); + ListResponse<UcsBladeResponse> listUcsBlades(ListUcsBladeCmd cmd); void deleteUcsManager(Long id); + + ListResponse<UcsBladeResponse> refreshBlades(Long mgrId); + + UcsBladeResponse disassociateProfile(DisassociateUcsProfileCmd cmd); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ef6038f1/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManagerImpl.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManagerImpl.java b/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManagerImpl.java index 4239482..7c9aff0 100755 --- a/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManagerImpl.java +++ b/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManagerImpl.java @@ -17,33 +17,6 @@ // package com.cloud.ucs.manager; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import javax.ejb.Local; -import javax.inject.Inject; -import javax.naming.ConfigurationException; - -import org.apache.log4j.Logger; -import org.apache.cloudstack.api.AddUcsManagerCmd; -import org.apache.cloudstack.api.AssociateUcsProfileToBladeCmd; -import org.apache.cloudstack.api.DeleteUcsManagerCmd; -import org.apache.cloudstack.api.ListUcsBladeCmd; -import org.apache.cloudstack.api.ListUcsManagerCmd; -import org.apache.cloudstack.api.ListUcsProfileCmd; -import org.apache.cloudstack.api.response.ListResponse; -import org.apache.cloudstack.api.response.UcsBladeResponse; -import org.apache.cloudstack.api.response.UcsManagerResponse; -import org.apache.cloudstack.api.response.UcsProfileResponse; -import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.cloudstack.managed.context.ManagedContextRunnable; - import com.cloud.configuration.Config; import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.DataCenterVO; @@ -59,14 +32,26 @@ import com.cloud.ucs.database.UcsManagerVO; import com.cloud.ucs.structure.ComputeBlade; import com.cloud.ucs.structure.UcsCookie; import com.cloud.ucs.structure.UcsProfile; +import com.cloud.ucs.structure.UcsTemplate; import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.DB; -import com.cloud.utils.db.QueryBuilder; +import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria.Op; -import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.xmlobject.XmlObject; import com.cloud.utils.xmlobject.XmlObjectParser; +import org.apache.cloudstack.api.*; +import org.apache.cloudstack.api.response.*; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.log4j.Logger; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; +import java.util.*; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; @Local(value = { UcsManager.class }) public class UcsManagerImpl implements UcsManager { @@ -98,7 +83,7 @@ public class UcsManagerImpl implements UcsManager { private ScheduledExecutorService syncBladesExecutor; private int syncBladeInterval; - private class SyncBladesThread extends ManagedContextRunnable { + private class SyncBladesThread implements Runnable { private void discoverNewBlades(Map<String, UcsBladeVO> previous, Map<String, ComputeBlade> now, UcsManagerVO mgr) { @@ -132,9 +117,9 @@ public class UcsManagerImpl implements UcsManager { } private void syncBlades(UcsManagerVO mgr) { - QueryBuilder<UcsBladeVO> q = QueryBuilder.create(UcsBladeVO.class); - q.and(q.entity().getUcsManagerId(), Op.EQ, mgr.getId()); - List<UcsBladeVO> pblades = q.list(); + SearchCriteria<UcsBladeVO> q = bladeDao.createSearchCriteria(); + q.addAnd("ucsManagerId", Op.EQ, mgr.getId()); + List<UcsBladeVO> pblades = bladeDao.search(q, null); if (pblades.isEmpty()) { return; } @@ -156,7 +141,7 @@ public class UcsManagerImpl implements UcsManager { } @Override - protected void runInContext() { + public void run() { try { List<UcsManagerVO> mgrs = ucsDao.listAll(); for (UcsManagerVO mgr : mgrs) { @@ -203,6 +188,9 @@ public class UcsManagerImpl implements UcsManager { vo.setDn(b.getDn()); vo.setUcsManagerId(ucsMgrVo.getId()); vo.setUuid(UUID.randomUUID().toString()); + if (!"".equals(b.getAssignedToDn())) { + vo.setProfileDn(b.getAssignedToDn()); + } bladeDao.persist(vo); } } @@ -210,9 +198,9 @@ public class UcsManagerImpl implements UcsManager { @Override @DB public UcsManagerResponse addUcsManager(AddUcsManagerCmd cmd) { - QueryBuilder<UcsManagerVO> q = QueryBuilder.create(UcsManagerVO.class); - q.and(q.entity().getUrl(), Op.EQ, cmd.getUrl()); - UcsManagerVO mgrvo = q.find(); + SearchCriteria<UcsManagerVO> q = ucsDao.createSearchCriteria(); + q.addAnd("url", Op.EQ, cmd.getUrl()); + UcsManagerVO mgrvo = ucsDao.findOneBy(q); if (mgrvo != null) { throw new IllegalArgumentException(String.format("duplicate UCS manager. url[%s] is used by another UCS manager already", cmd.getUrl())); } @@ -263,7 +251,7 @@ public class UcsManagerImpl implements UcsManager { cmd = UcsCommands.refreshCmd(mgrvo.getUsername(), mgrvo.getPassword(), cookie); } } - if(!(cmd == null)) { + if(cmd != null) { String ret = client.call(cmd); XmlObject xo = XmlObjectParser.parseFromString(ret); String cookie = xo.get("outCookie"); @@ -286,14 +274,24 @@ public class UcsManagerImpl implements UcsManager { return ComputeBlade.fromXmString(ret); } + private List<UcsTemplate> getUcsTemplates(Long ucsMgrId) { + String cookie = getCookie(ucsMgrId); + UcsManagerVO mgrvo = ucsDao.findById(ucsMgrId); + String cmd = UcsCommands.listTemplates(cookie); + UcsHttpClient client = new UcsHttpClient(mgrvo.getUrl()); + String res = client.call(cmd); + List<UcsTemplate> tmps = UcsTemplate.fromXmlString(res); + return tmps; + } + private List<UcsProfile> getUcsProfiles(Long ucsMgrId) { String cookie = getCookie(ucsMgrId); UcsManagerVO mgrvo = ucsDao.findById(ucsMgrId); - String cmd = UcsCommands.listProfiles(cookie); + String cmd = UcsCommands.listTemplates(cookie); UcsHttpClient client = new UcsHttpClient(mgrvo.getUrl()); String res = client.call(cmd); - List<UcsProfile> profiles = UcsProfile.fromXmlString(res); - return profiles; + List<UcsTemplate> tmps = UcsTemplate.fromXmlString(res); + return null; } @Override @@ -311,6 +309,21 @@ public class UcsManagerImpl implements UcsManager { return response; } + @Override + public ListResponse<UcsTemplateResponse> listUcsTemplates(ListUcsTemplatesCmd cmd) { + List<UcsTemplate> templates = getUcsTemplates(cmd.getUcsManagerId()); + ListResponse<UcsTemplateResponse> response = new ListResponse<UcsTemplateResponse>(); + List<UcsTemplateResponse> rs = new ArrayList<UcsTemplateResponse>(); + for (UcsTemplate t : templates) { + UcsTemplateResponse r = new UcsTemplateResponse(); + r.setObjectName("ucstemplate"); + r.setDn(t.getDn()); + rs.add(r); + } + response.setResponses(rs); + return response; + } + private String cloneProfile(Long ucsMgrId, String srcDn, String newProfileName) { UcsManagerVO mgrvo = ucsDao.findById(ucsMgrId); UcsHttpClient client = new UcsHttpClient(mgrvo.getUrl()); @@ -321,6 +334,7 @@ public class UcsManagerImpl implements UcsManager { return xo.get("outConfig.lsServer.dn"); } + private boolean isProfileAssociated(Long ucsMgrId, String dn) { UcsManagerVO mgrvo = ucsDao.findById(ucsMgrId); UcsHttpClient client = new UcsHttpClient(mgrvo.getUrl()); @@ -328,21 +342,33 @@ public class UcsManagerImpl implements UcsManager { String cmd = UcsCommands.configResolveDn(cookie, dn); String res = client.call(cmd); XmlObject xo = XmlObjectParser.parseFromString(res); + + return xo.get("outConfig.lsServer.assocState").equals("associated"); + } + + private boolean isBladeAssociated(Long ucsMgrId, String dn) { + UcsManagerVO mgrvo = ucsDao.findById(ucsMgrId); + UcsHttpClient client = new UcsHttpClient(mgrvo.getUrl()); + String cookie = getCookie(ucsMgrId); + String cmd = UcsCommands.configResolveDn(cookie, dn); + String res = client.call(cmd); + XmlObject xo = XmlObjectParser.parseFromString(res); s_logger.debug(String.format("association response is %s", res)); if (xo.get("outConfig.computeBlade.association").equals("none")) { throw new CloudRuntimeException(String.format("cannot associated a profile to blade[dn:%s]. please check your UCS manasger for detailed error information", dn)); } - + return xo.get("outConfig.computeBlade.association").equals("associated"); + //return !xo.get("outConfig.computeBlade.assignedToDn").equals(""); } @Override public UcsBladeResponse associateProfileToBlade(AssociateUcsProfileToBladeCmd cmd) { - QueryBuilder<UcsBladeVO> q = QueryBuilder.create(UcsBladeVO.class); - q.and(q.entity().getUcsManagerId(), Op.EQ, cmd.getUcsManagerId()); - q.and(q.entity().getId(), Op.EQ, cmd.getBladeId()); - UcsBladeVO bvo = q.find(); + SearchCriteria<UcsBladeVO> sc = bladeDao.createSearchCriteria(); + sc.addAnd("ucsManagerId", Op.EQ, cmd.getUcsManagerId()); + sc.addAnd("id", Op.EQ, cmd.getBladeId()); + UcsBladeVO bvo = bladeDao.findOneBy(sc); if (bvo == null) { throw new IllegalArgumentException(String.format("cannot find UCS blade[id:%s, ucs manager id:%s]", cmd.getBladeId(), cmd.getUcsManagerId())); } @@ -358,9 +384,9 @@ public class UcsManagerImpl implements UcsManager { UcsHttpClient client = new UcsHttpClient(mgrvo.getUrl()); String res = client.call(ucscmd); int count = 0; - int timeout = 600; + int timeout = 3600; while (count < timeout) { - if (isProfileAssociated(mgrvo.getId(), bvo.getDn())) { + if (isBladeAssociated(mgrvo.getId(), bvo.getDn())) { break; } @@ -386,6 +412,63 @@ public class UcsManagerImpl implements UcsManager { return rsp; } + @Override + public UcsBladeResponse instantiateTemplateAndAssociateToBlade(InstantiateUcsTemplateAndAssociateToBladeCmd cmd) { + String profileName = cmd.getProfileName(); + if (profileName == null || "".equals(profileName)) { + profileName = UUID.randomUUID().toString().replace("-", ""); + } + + SearchCriteria<UcsBladeVO> sc = bladeDao.createSearchCriteria(); + sc.addAnd("ucsManagerId", Op.EQ, cmd.getUcsManagerId()); + sc.addAnd("id", Op.EQ, cmd.getBladeId()); + UcsBladeVO bvo = bladeDao.findOneBy(sc); + if (bvo == null) { + throw new IllegalArgumentException(String.format("cannot find UCS blade[id:%s, ucs manager id:%s]", cmd.getBladeId(), cmd.getUcsManagerId())); + } + + if (bvo.getHostId() != null) { + throw new CloudRuntimeException(String.format("blade[id:%s, dn:%s] has been associated with host[id:%s]", bvo.getId(), bvo.getDn(), bvo.getHostId())); + } + + UcsManagerVO mgrvo = ucsDao.findById(cmd.getUcsManagerId()); + String cookie = getCookie(cmd.getUcsManagerId()); + String instantiateTemplateCmd = UcsCommands.instantiateTemplate(cookie, cmd.getTemplateDn(), profileName); + UcsHttpClient http = new UcsHttpClient(mgrvo.getUrl()); + String res = http.call(instantiateTemplateCmd); + XmlObject xo = XmlObjectParser.parseFromString(res); + String profileDn = xo.get("outConfig.lsServer.dn"); + String ucscmd = UcsCommands.associateProfileToBlade(cookie, profileDn, bvo.getDn()); + res = http.call(ucscmd); + int count = 0; + int timeout = 3600; + while (count < timeout) { + if (isBladeAssociated(mgrvo.getId(), bvo.getDn())) { + break; + } + + try { + TimeUnit.SECONDS.sleep(2); + } catch (InterruptedException e) { + throw new CloudRuntimeException(e); + } + + count += 2; + } + + if (count >= timeout) { + throw new CloudRuntimeException(String.format("associating profile[%s] to balde[%s] timeout after 600 seconds", profileDn, bvo.getDn())); + } + + bvo.setProfileDn(profileDn); + bladeDao.update(bvo.getId(), bvo); + + UcsBladeResponse rsp = bladeVOToResponse(bvo); + + s_logger.debug(String.format("successfully associated profile[%s] to blade[%s]", profileDn, bvo.getDn())); + return rsp; + } + private String hostIdToUuid(Long hostId) { if (hostId == null) { return null; @@ -420,10 +503,10 @@ public class UcsManagerImpl implements UcsManager { response.setResponses(rsps); return response; } - - QueryBuilder<UcsManagerVO> serv = QueryBuilder.create(UcsManagerVO.class); - serv.and(serv.entity().getZoneId(), Op.EQ, cmd.getZoneId()); - List<UcsManagerVO> vos = serv.list(); + + SearchCriteria<UcsManagerVO> sc = ucsDao.createSearchCriteria(); + sc.addAnd("zoneId", Op.EQ, cmd.getZoneId()); + List<UcsManagerVO> vos = ucsDao.search(sc, null); for (UcsManagerVO vo : vos) { UcsManagerResponse rsp = new UcsManagerResponse(); @@ -448,19 +531,18 @@ public class UcsManagerImpl implements UcsManager { rsp.setUcsManagerId(ucsManagerIdToUuid(vo.getUcsManagerId())); return rsp; } - - @Override - public ListResponse<UcsBladeResponse> listUcsBlades(ListUcsBladeCmd cmd) { - QueryBuilder<UcsBladeVO> serv = QueryBuilder.create(UcsBladeVO.class); - serv.and(serv.entity().getUcsManagerId(), Op.EQ, cmd.getUcsManagerId()); - List<UcsBladeVO> vos = serv.list(); - + + private ListResponse<UcsBladeResponse> listUcsBlades(long mgrId) { + SearchCriteria<UcsBladeVO> sc = bladeDao.createSearchCriteria(); + sc.addAnd("ucsManagerId", Op.EQ, mgrId); + List<UcsBladeVO> vos = bladeDao.search(sc, null); + List<UcsBladeResponse> rsps = new ArrayList<UcsBladeResponse>(vos.size()); for (UcsBladeVO vo : vos) { UcsBladeResponse rsp = bladeVOToResponse(vo); rsps.add(rsp); } - + ListResponse<UcsBladeResponse> response = new ListResponse<UcsBladeResponse>(); response.setResponses(rsps); @@ -468,6 +550,11 @@ public class UcsManagerImpl implements UcsManager { } @Override + public ListResponse<UcsBladeResponse> listUcsBlades(ListUcsBladeCmd cmd) { + return listUcsBlades(cmd.getUcsManagerId()); + } + + @Override public void setName(String name) { this.name = name; } @@ -501,17 +588,68 @@ public class UcsManagerImpl implements UcsManager { cmds.add(AddUcsManagerCmd.class); cmds.add(AssociateUcsProfileToBladeCmd.class); cmds.add(DeleteUcsManagerCmd.class); + cmds.add(DisassociateUcsProfileCmd.class); + cmds.add(RefreshUcsBladesCmd.class); + cmds.add(ListUcsTemplatesCmd.class); + cmds.add(InstantiateUcsTemplateAndAssociateToBladeCmd.class); return cmds; } @Override public void deleteUcsManager(Long id) { - QueryBuilder<UcsBladeVO> serv = QueryBuilder.create(UcsBladeVO.class); - serv.and(serv.entity().getUcsManagerId(), Op.EQ, id); - List<UcsBladeVO> vos = serv.list(); + SearchCriteria<UcsBladeVO> sc = bladeDao.createSearchCriteria(); + sc.addAnd("ucsManagerId", Op.EQ, id); + List<UcsBladeVO> vos = bladeDao.search(sc, null); for (UcsBladeVO vo : vos) { bladeDao.remove(vo.getId()); } ucsDao.remove(id); } + + @Override + @DB + public ListResponse<UcsBladeResponse> refreshBlades(Long mgrId) { + SyncBladesThread synct = new SyncBladesThread(); + synct.run(); + + UcsManagerVO mgrvo = ucsDao.findById(mgrId); + List<ComputeBlade> blades = listBlades(mgrvo.getId()); + for (ComputeBlade b : blades) { + SearchCriteria<UcsBladeVO> sc = bladeDao.createSearchCriteria(); + sc.addAnd("dn", Op.EQ, b.getDn()); + UcsBladeVO vo = bladeDao.findOneBy(sc); + if (vo == null) { + vo = new UcsBladeVO(); + vo.setProfileDn("".equals(b.getAssignedToDn()) ? null : b.getAssignedToDn()); + vo.setDn(b.getDn()); + vo.setUuid(UUID.randomUUID().toString()); + vo.setUcsManagerId(mgrId); + bladeDao.persist(vo); + } else { + vo.setProfileDn("".equals(b.getAssignedToDn()) ? null : b.getAssignedToDn()); + bladeDao.update(vo.getId(), vo); + } + } + + return listUcsBlades(mgrId); + } + + @Override + public UcsBladeResponse disassociateProfile(DisassociateUcsProfileCmd cmd) { + UcsBladeVO blade = bladeDao.findById(cmd.getBladeId()); + UcsManagerVO mgrvo = ucsDao.findById(blade.getUcsManagerId()); + UcsHttpClient client = new UcsHttpClient(mgrvo.getUrl()); + String cookie = getCookie(mgrvo.getId()); + String call = UcsCommands.disassociateProfileFromBlade(cookie, blade.getProfileDn()); + client.call(call); + if (cmd.isDeleteProfile()) { + call = UcsCommands.deleteProfile(cookie, blade.getProfileDn()); + client = new UcsHttpClient(mgrvo.getUrl()); + client.call(call); + } + blade.setProfileDn(null); + bladeDao.update(blade.getId(), blade); + UcsBladeResponse rsp = bladeVOToResponse(blade); + return rsp; + } }