Updated Branches: refs/heads/4.2 999c1bc1c -> 8edaf63c4
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/8edaf63c Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/8edaf63c Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/8edaf63c Branch: refs/heads/4.2 Commit: 8edaf63c4e4a054b17a2dfe4233d103fb2ee9e6a Parents: 999c1bc Author: Frank.Zhang <frank.zh...@citrix.com> Authored: Thu Oct 10 14:45:03 2013 -0700 Committer: Frank.Zhang <frank.zh...@citrix.com> Committed: Thu Oct 10 14:45:03 2013 -0700 ---------------------------------------------------------------------- api/src/com/cloud/event/EventTypes.java | 2 + .../org/apache/cloudstack/api/ApiConstants.java | 3 + client/tomcatconf/commands.properties.in | 3 + .../src/com/cloud/ucs/manager/UcsCommands.java | 85 +++++---- .../com/cloud/ucs/manager/UcsHttpClient.java | 61 ++++++- .../src/com/cloud/ucs/manager/UcsManager.java | 19 +- .../com/cloud/ucs/manager/UcsManagerImpl.java | 173 +++++++++++++++---- .../com/cloud/ucs/structure/UcsTemplate.java | 40 +++++ .../api/DisassociateUcsProfileCmd.java | 21 ++- ...ntiateUcsTemplateAndAssociateToBladeCmd.java | 99 +++++++++++ .../cloudstack/api/ListUcsTemplatesCmd.java | 55 ++++++ .../cloudstack/api/RefreshUcsBladesCmd.java | 71 ++++++++ .../api/response/UcsTemplateResponse.java | 36 ++++ 13 files changed, 588 insertions(+), 80 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8edaf63c/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 dc20400..1f5b5b7 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -443,7 +443,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"; static { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8edaf63c/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 14e1c96..d71db40 100755 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -493,8 +493,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/8edaf63c/client/tomcatconf/commands.properties.in ---------------------------------------------------------------------- diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 492661e..d4aff29 100644 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -616,9 +616,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/8edaf63c/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 52e5edf..8232844 100755 --- 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); @@ -93,38 +114,38 @@ public class UcsCommands { 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/8edaf63c/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 7758c4c..d3dd483 100755 --- a/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsHttpClient.java +++ b/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsHttpClient.java @@ -17,24 +17,31 @@ // package com.cloud.ucs.manager; -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; -import org.apache.commons.httpclient.URI; 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 com.cloud.utils.exception.CloudRuntimeException; +import org.apache.log4j.Logger; +import org.springframework.http.*; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.web.client.RestTemplate; + +import java.net.URI; +import java.net.URISyntaxException; public class UcsHttpClient { - private static HttpClient client; + 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(); + //client = new HttpClient(); + template = new RestTemplate(); } public UcsHttpClient(String ip) { @@ -42,7 +49,46 @@ public class UcsHttpClient { 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); + 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().value() == 302) { + // 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); + } + 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"); @@ -80,5 +126,6 @@ public class UcsHttpClient { } finally { post.releaseConnection(); } + */ } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8edaf63c/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 babec3a..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,13 +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); - UcsBladeResponse disassociateProfile(Long bladeId); + ListResponse<UcsBladeResponse> refreshBlades(Long mgrId); + + UcsBladeResponse disassociateProfile(DisassociateUcsProfileCmd cmd); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8edaf63c/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 4000e98..68c05f7 100755 --- a/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManagerImpl.java +++ b/plugins/hypervisors/ucs/src/com/cloud/ucs/manager/UcsManagerImpl.java @@ -30,11 +30,9 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.ucs.structure.UcsTemplate; import org.apache.cloudstack.api.*; -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.response.*; import org.apache.log4j.Logger; import com.cloud.configuration.Config; @@ -198,6 +196,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); } } @@ -261,7 +262,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"); @@ -284,21 +285,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); - List<UcsProfile> unassociated = new ArrayList<UcsProfile>(); - for (UcsProfile p : profiles) { - if (isProfileAssociated(mgrvo.getId(), p.getDn())) { - continue; - } - unassociated.add(p); - } - return unassociated; + List<UcsTemplate> tmps = UcsTemplate.fromXmlString(res); + return null; } @Override @@ -316,6 +320,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()); @@ -350,8 +369,9 @@ public class UcsManagerImpl implements UcsManager { 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.lsServer.assocState").equals("associated"); + //return !xo.get("outConfig.computeBlade.assignedToDn").equals(""); } @Override @@ -403,6 +423,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("-", ""); + } + + SearchCriteriaService<UcsBladeVO, UcsBladeVO> q = SearchCriteria2.create(UcsBladeVO.class); + q.addAnd(q.getEntity().getUcsManagerId(), Op.EQ, cmd.getUcsManagerId()); + q.addAnd(q.getEntity().getId(), Op.EQ, cmd.getBladeId()); + UcsBladeVO bvo = q.find(); + 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; @@ -465,19 +542,18 @@ public class UcsManagerImpl implements UcsManager { rsp.setUcsManagerId(ucsManagerIdToUuid(vo.getUcsManagerId())); return rsp; } - - @Override - public ListResponse<UcsBladeResponse> listUcsBlades(ListUcsBladeCmd cmd) { + + private ListResponse<UcsBladeResponse> listUcsBlades(long mgrId) { SearchCriteriaService<UcsBladeVO, UcsBladeVO> serv = SearchCriteria2.create(UcsBladeVO.class); - serv.addAnd(serv.getEntity().getUcsManagerId(), Op.EQ, cmd.getUcsManagerId()); + serv.addAnd(serv.getEntity().getUcsManagerId(), Op.EQ, mgrId); List<UcsBladeVO> vos = serv.list(); - + 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); @@ -485,6 +561,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; } @@ -519,6 +600,9 @@ public class UcsManagerImpl implements UcsManager { 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; } @@ -534,16 +618,45 @@ public class UcsManagerImpl implements UcsManager { } @Override - public UcsBladeResponse disassociateProfile(Long bladeId) { - UcsBladeVO blade = bladeDao.findById(bladeId); + 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) { + SearchCriteria2<UcsBladeVO, UcsBladeVO> q = SearchCriteria2.create(UcsBladeVO.class, UcsBladeVO.class); + q.addAnd(q.getEntity().getDn(), Op.EQ, b.getDn()); + UcsBladeVO vo = q.find(); + 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 cmd = UcsCommands.disassociateProfileFromBlade(cookie, blade.getProfileDn()); - client.call(cmd); - cmd = UcsCommands.deleteProfile(cookie, blade.getProfileDn()); - client = new UcsHttpClient(mgrvo.getUrl()); - client.call(cmd); + 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); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8edaf63c/plugins/hypervisors/ucs/src/com/cloud/ucs/structure/UcsTemplate.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ucs/src/com/cloud/ucs/structure/UcsTemplate.java b/plugins/hypervisors/ucs/src/com/cloud/ucs/structure/UcsTemplate.java new file mode 100644 index 0000000..e879e15 --- /dev/null +++ b/plugins/hypervisors/ucs/src/com/cloud/ucs/structure/UcsTemplate.java @@ -0,0 +1,40 @@ +package com.cloud.ucs.structure; + +import com.cloud.utils.xmlobject.XmlObject; +import com.cloud.utils.xmlobject.XmlObjectParser; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created with IntelliJ IDEA. + * User: frank + * Date: 10/8/13 + * Time: 3:01 PM + * To change this template use File | Settings | File Templates. + */ +public class UcsTemplate { + private String dn; + + public static List<UcsTemplate> fromXmlString(String xmlstr) { + List<UcsTemplate> tmps = new ArrayList<UcsTemplate>(); + XmlObject xo = XmlObjectParser.parseFromString(xmlstr); + List<XmlObject> xos = xo.getAsList("outConfigs.lsServer"); + if (xos != null) { + for (XmlObject x : xos) { + UcsTemplate t = new UcsTemplate(); + t.setDn(x.get("dn").toString()); + tmps.add(t); + } + } + return tmps; + } + + public String getDn() { + return dn; + } + + public void setDn(String dn) { + this.dn = dn; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8edaf63c/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/DisassociateUcsProfileCmd.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/DisassociateUcsProfileCmd.java b/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/DisassociateUcsProfileCmd.java index ed20989..751542d 100755 --- a/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/DisassociateUcsProfileCmd.java +++ b/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/DisassociateUcsProfileCmd.java @@ -27,6 +27,9 @@ public class DisassociateUcsProfileCmd extends BaseAsyncCmd { @Parameter(name=ApiConstants.UCS_BLADE_ID, type=CommandType.UUID, entityType=UcsBladeResponse.class, description="blade id", required=true) private Long bladeId; + @Parameter(name=ApiConstants.UCS_DELETE_PROFILE, type=CommandType.BOOLEAN, description="is deleting profile after disassociating") + private boolean deleteProfile; + @Override public String getEventType() { return EventTypes.EVENT_UCS_DISASSOCIATED_PROFILE; @@ -37,10 +40,26 @@ public class DisassociateUcsProfileCmd extends BaseAsyncCmd { return "disassociate a profile from blade"; } + public Long getBladeId() { + return bladeId; + } + + public void setBladeId(Long bladeId) { + this.bladeId = bladeId; + } + + public boolean isDeleteProfile() { + return deleteProfile; + } + + public void setDeleteProfile(boolean deleteProfile) { + this.deleteProfile = deleteProfile; + } + @Override public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { try { - UcsBladeResponse rsp = mgr.disassociateProfile(bladeId); + UcsBladeResponse rsp = mgr.disassociateProfile(this); rsp.setResponseName(getCommandName()); this.setResponseObject(rsp); } catch(Exception e) { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8edaf63c/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/InstantiateUcsTemplateAndAssociateToBladeCmd.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/InstantiateUcsTemplateAndAssociateToBladeCmd.java b/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/InstantiateUcsTemplateAndAssociateToBladeCmd.java new file mode 100644 index 0000000..bd9a0f8 --- /dev/null +++ b/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/InstantiateUcsTemplateAndAssociateToBladeCmd.java @@ -0,0 +1,99 @@ +package org.apache.cloudstack.api; + +import com.cloud.event.EventTypes; +import com.cloud.exception.*; +import com.cloud.ucs.manager.UcsManager; +import com.cloud.user.Account; +import org.apache.cloudstack.api.response.UcsBladeResponse; +import org.apache.cloudstack.api.response.UcsManagerResponse; +import org.apache.log4j.Logger; + +import javax.inject.Inject; + +/** + * Created with IntelliJ IDEA. + * User: frank + * Date: 10/8/13 + * Time: 3:17 PM + * To change this template use File | Settings | File Templates. + */ +@APICommand(name="instantiateUcsTemplateAndAssocaciateToBlade", description="create a profile of template and associate to a blade", responseObject=UcsBladeResponse.class) +public class InstantiateUcsTemplateAndAssociateToBladeCmd extends BaseAsyncCmd{ + public static final Logger s_logger = Logger.getLogger(InstantiateUcsTemplateAndAssociateToBladeCmd.class); + + @Inject + private UcsManager mgr; + + @Parameter(name=ApiConstants.UCS_MANAGER_ID, type= BaseCmd.CommandType.UUID, description="ucs manager id", entityType=UcsManagerResponse.class, required=true) + private Long ucsManagerId; + @Parameter(name=ApiConstants.UCS_TEMPLATE_DN, type= BaseCmd.CommandType.STRING, description="template dn", required=true) + private String templateDn; + @Parameter(name=ApiConstants.UCS_BLADE_ID, type= BaseCmd.CommandType.UUID, entityType=UcsBladeResponse.class, description="blade id", required=true) + private Long bladeId; + @Parameter(name=ApiConstants.UCS_PROFILE_NAME, type= BaseCmd.CommandType.STRING, description="profile name") + private String profileName; + + @Override + public String getEventType() { + return EventTypes.EVENT_UCS_INSTANTIATE_TEMPLATE_AND_ASSOCIATE; + } + + @Override + public String getEventDescription() { + return "create a profile off template and associate to a blade"; + } + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + try { + UcsBladeResponse rsp = mgr.instantiateTemplateAndAssociateToBlade(this); + rsp.setResponseName(getCommandName()); + this.setResponseObject(rsp); + } catch (Exception e) { + s_logger.warn("Exception: ", e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); + } + } + + @Override + public String getCommandName() { + return "instantiateucstemplateandassociatetobladeresponse"; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + public Long getUcsManagerId() { + return ucsManagerId; + } + + public void setUcsManagerId(Long ucsManagerId) { + this.ucsManagerId = ucsManagerId; + } + + public String getTemplateDn() { + return templateDn; + } + + public void setTemplateDn(String templateDn) { + this.templateDn = templateDn; + } + + public Long getBladeId() { + return bladeId; + } + + public void setBladeId(Long bladeId) { + this.bladeId = bladeId; + } + + public String getProfileName() { + return profileName; + } + + public void setProfileName(String profileName) { + this.profileName = profileName; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8edaf63c/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/ListUcsTemplatesCmd.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/ListUcsTemplatesCmd.java b/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/ListUcsTemplatesCmd.java new file mode 100644 index 0000000..7ae1222 --- /dev/null +++ b/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/ListUcsTemplatesCmd.java @@ -0,0 +1,55 @@ +package org.apache.cloudstack.api; + +import com.cloud.exception.*; +import com.cloud.ucs.manager.UcsManager; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.UcsManagerResponse; +import org.apache.cloudstack.api.response.UcsProfileResponse; +import org.apache.cloudstack.api.response.UcsTemplateResponse; +import org.apache.log4j.Logger; + +import javax.inject.Inject; + +/** + * Created with IntelliJ IDEA. + * User: frank + * Date: 10/8/13 + * Time: 3:08 PM + * To change this template use File | Settings | File Templates. + */ +@APICommand(name="listUcsTemplates", description="List templates in ucs manager", responseObject=UcsTemplateResponse.class) +public class ListUcsTemplatesCmd extends BaseListCmd { + public static final Logger s_logger = Logger.getLogger(ListUcsTemplatesCmd.class); + + @Inject + UcsManager mgr; + + @Parameter(name=ApiConstants.UCS_MANAGER_ID, type= BaseCmd.CommandType.UUID, entityType=UcsManagerResponse.class, description="the id for the ucs manager", required=true) + private Long ucsManagerId; + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + try { + ListResponse<UcsTemplateResponse> response = mgr.listUcsTemplates(this); + response.setResponseName(getCommandName()); + response.setObjectName("ucstemplate"); + this.setResponseObject(response); + } catch (Exception e) { + s_logger.warn("Exception: ", e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); + } + } + + @Override + public String getCommandName() { + return "listucstemplatesresponse"; + } + + public Long getUcsManagerId() { + return ucsManagerId; + } + + public void setUcsManagerId(Long ucsManagerId) { + this.ucsManagerId = ucsManagerId; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8edaf63c/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/RefreshUcsBladesCmd.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/RefreshUcsBladesCmd.java b/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/RefreshUcsBladesCmd.java new file mode 100644 index 0000000..b7249d1 --- /dev/null +++ b/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/RefreshUcsBladesCmd.java @@ -0,0 +1,71 @@ +package org.apache.cloudstack.api; + +import com.cloud.event.EventTypes; +import com.cloud.exception.*; +import com.cloud.ucs.manager.UcsManager; +import com.cloud.user.Account; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.UcsBladeResponse; +import org.apache.cloudstack.api.response.UcsManagerResponse; +import org.apache.log4j.Logger; + +import javax.inject.Inject; + +/** + * Created with IntelliJ IDEA. + * User: frank + * Date: 10/3/13 + * Time: 2:18 PM + * To change this template use File | Settings | File Templates. + */ +@APICommand(name="refreshUcsBlades", description="refresh ucs blades to sync with UCS manager", responseObject=UcsBladeResponse.class) +public class RefreshUcsBladesCmd extends BaseAsyncCmd { + private static Logger s_logger = Logger.getLogger(RefreshUcsBladesCmd.class); + + @Inject + private UcsManager mgr; + + @Parameter(name=ApiConstants.UCS_MANAGER_ID, type= BaseCmd.CommandType.UUID, description="ucs manager id", entityType=UcsManagerResponse.class, required=true) + private Long ucsManagerId; + + public UcsManager getMgr() { + return mgr; + } + + public void setMgr(UcsManager mgr) { + this.mgr = mgr; + } + + @Override + public String getEventType() { + return EventTypes.EVENT_UCS_REFRESH_BLADES; + } + + @Override + public String getEventDescription() { + return "refresh ucs blades status to sync with UCS manager"; + } + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + try { + ListResponse<UcsBladeResponse> response = mgr.refreshBlades(ucsManagerId); + response.setResponseName(getCommandName()); + response.setObjectName("ucsblade"); + this.setResponseObject(response); + } catch (Exception e) { + s_logger.warn("unhandled exception:", e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); + } + } + + @Override + public String getCommandName() { + return "refreshucsbladesresponse"; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8edaf63c/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/response/UcsTemplateResponse.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/response/UcsTemplateResponse.java b/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/response/UcsTemplateResponse.java new file mode 100644 index 0000000..0a31dae --- /dev/null +++ b/plugins/hypervisors/ucs/src/org/apache/cloudstack/api/response/UcsTemplateResponse.java @@ -0,0 +1,36 @@ +// 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.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; + +public class UcsTemplateResponse extends BaseResponse { + @SerializedName(ApiConstants.UCS_DN) @Param(description="ucs template dn") + private String dn; + + public String getDn() { + return dn; + } + + public void setDn(String dn) { + this.dn = dn; + } +}