Updated Branches: refs/heads/vmsync 9786f7b7b -> 86053cd8b
Add VM work job dispatcher, MethodCapturer etc Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/86053cd8 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/86053cd8 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/86053cd8 Branch: refs/heads/vmsync Commit: 86053cd8b26417bddb2fde76185ee835a79fb01c Parents: 9786f7b Author: Kelven Yang <[email protected]> Authored: Tue Apr 30 18:12:23 2013 -0700 Committer: Kelven Yang <[email protected]> Committed: Tue Apr 30 18:12:23 2013 -0700 ---------------------------------------------------------------------- api/src/com/cloud/deploy/DataCenterDeployment.java | 4 + api/src/com/cloud/vm/VirtualMachineProfile.java | 22 +++ .../framework/async/AsyncCallbackDispatcher.java | 2 +- .../src/com/cloud/api/ApiAsyncJobDispatcher.java | 2 - server/src/com/cloud/api/ApiSerializerHelper.java | 2 +- .../src/com/cloud/async/AsyncJobManagerImpl.java | 6 +- server/src/com/cloud/async/AsyncJobResult.java | 2 +- .../com/cloud/vm/VirtualMachineManagerImpl.java | 11 ++ server/src/com/cloud/vm/VmWork.java | 54 +++++++ server/src/com/cloud/vm/VmWorkJobDispatcher.java | 58 ++++++++ server/src/com/cloud/vm/VmWorkStart.java | 74 ++++++++++ server/test/com/cloud/keystore/KeystoreTest.java | 4 +- .../cloud/vm/VirtualMachineManagerImplTest.java | 4 - server/test/com/cloud/vm/VmWorkTest.java | 61 ++++++++ utils/src/com/cloud/utils/EnumUtils.java | 13 ++ utils/src/com/cloud/utils/MethodCapturer.java | 113 +++++++++++++++ utils/test/com/cloud/utils/DummyImpl.java | 4 + utils/test/com/cloud/utils/MethodCatpurerTest.java | 37 +++++ 18 files changed, 459 insertions(+), 14 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/86053cd8/api/src/com/cloud/deploy/DataCenterDeployment.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/deploy/DataCenterDeployment.java b/api/src/com/cloud/deploy/DataCenterDeployment.java index f046b66..92bb9b9 100644 --- a/api/src/com/cloud/deploy/DataCenterDeployment.java +++ b/api/src/com/cloud/deploy/DataCenterDeployment.java @@ -30,6 +30,10 @@ public class DataCenterDeployment implements DeploymentPlan { boolean _recreateDisks; ReservationContext _context; + public DataCenterDeployment() { + _dcId = 0; + } + public DataCenterDeployment(long dataCenterId) { this(dataCenterId, null, null, null, null, null); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/86053cd8/api/src/com/cloud/vm/VirtualMachineProfile.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/vm/VirtualMachineProfile.java b/api/src/com/cloud/vm/VirtualMachineProfile.java index 33a9171..c79b042 100644 --- a/api/src/com/cloud/vm/VirtualMachineProfile.java +++ b/api/src/com/cloud/vm/VirtualMachineProfile.java @@ -36,6 +36,7 @@ import com.cloud.user.Account; */ public interface VirtualMachineProfile<T extends VirtualMachine> { + // Making Param strong-typing looks like a over-kill to me public static class Param { public static final Param VmPassword = new Param("VmPassword"); @@ -56,6 +57,27 @@ public interface VirtualMachineProfile<T extends VirtualMachine> { public String getName() { return name; } + + // Param is used in HashMap data-structure, we need to provide hashCode() and equals in order to + // make HashMap work + @Override + public int hashCode() { + if(name != null) + return name.hashCode(); + return 0; + } + + @Override + public boolean equals(Object other) { + if(other == null) + return false; + + if(!(other instanceof Param)) + return false; + + assert(name != null); + return name.equals(((Param)other).getName()); + } } String getHostName(); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/86053cd8/framework/ipc/src/org/apache/cloudstack/framework/async/AsyncCallbackDispatcher.java ---------------------------------------------------------------------- diff --git a/framework/ipc/src/org/apache/cloudstack/framework/async/AsyncCallbackDispatcher.java b/framework/ipc/src/org/apache/cloudstack/framework/async/AsyncCallbackDispatcher.java index 26f46da..8d91f5f 100644 --- a/framework/ipc/src/org/apache/cloudstack/framework/async/AsyncCallbackDispatcher.java +++ b/framework/ipc/src/org/apache/cloudstack/framework/async/AsyncCallbackDispatcher.java @@ -56,7 +56,7 @@ public class AsyncCallbackDispatcher<T, R> implements AsyncCompletionCallback { public T getTarget() { Enhancer en = new Enhancer(); en.setSuperclass(_targetObject.getClass()); - en.setCallbacks(new Callback[]{new MethodInterceptor() { + en.setCallbacks(new Callback[] { new MethodInterceptor() { @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/86053cd8/server/src/com/cloud/api/ApiAsyncJobDispatcher.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/api/ApiAsyncJobDispatcher.java b/server/src/com/cloud/api/ApiAsyncJobDispatcher.java index 9c87378..ae7e0cf 100644 --- a/server/src/com/cloud/api/ApiAsyncJobDispatcher.java +++ b/server/src/com/cloud/api/ApiAsyncJobDispatcher.java @@ -31,7 +31,6 @@ import com.cloud.async.AsyncJob; import com.cloud.async.AsyncJobDispatcher; import com.cloud.async.AsyncJobManager; import com.cloud.async.AsyncJobResult; -import com.cloud.async.SyncQueueManager; import com.cloud.user.Account; import com.cloud.user.UserContext; import com.cloud.user.dao.AccountDao; @@ -46,7 +45,6 @@ public class ApiAsyncJobDispatcher extends AdapterBase implements AsyncJobDispat @Inject private ApiDispatcher _dispatcher; @Inject private AsyncJobManager _asyncJobMgr; - @Inject private SyncQueueManager _queueMgr; @Inject private AccountDao _accountDao; public ApiAsyncJobDispatcher() { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/86053cd8/server/src/com/cloud/api/ApiSerializerHelper.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/api/ApiSerializerHelper.java b/server/src/com/cloud/api/ApiSerializerHelper.java index 735330d..97faa19 100644 --- a/server/src/com/cloud/api/ApiSerializerHelper.java +++ b/server/src/com/cloud/api/ApiSerializerHelper.java @@ -25,7 +25,7 @@ public class ApiSerializerHelper { public static final Logger s_logger = Logger.getLogger(ApiSerializerHelper.class.getName()); public static String token = "/"; - public static String toSerializedStringOld(Object result) { + public static String toSerializedString(Object result) { if (result != null) { Class<?> clz = result.getClass(); Gson gson = ApiGsonHelper.getBuilder().create(); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/86053cd8/server/src/com/cloud/async/AsyncJobManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/async/AsyncJobManagerImpl.java b/server/src/com/cloud/async/AsyncJobManagerImpl.java index 49e1958..8b3d877 100644 --- a/server/src/com/cloud/async/AsyncJobManagerImpl.java +++ b/server/src/com/cloud/async/AsyncJobManagerImpl.java @@ -175,7 +175,7 @@ public class AsyncJobManagerImpl extends ManagerBase implements AsyncJobManager, job.setInstanceId(null); if (resultObject != null) { - job.setResult(ApiSerializerHelper.toSerializedStringOld(resultObject)); + job.setResult(ApiSerializerHelper.toSerializedString(resultObject)); } job.setLastUpdated(DateUtil.currentGMTTime()); @@ -209,7 +209,7 @@ public class AsyncJobManagerImpl extends ManagerBase implements AsyncJobManager, job.setProcessStatus(processStatus); if(resultObject != null) { - job.setResult(ApiSerializerHelper.toSerializedStringOld(resultObject)); + job.setResult(ApiSerializerHelper.toSerializedString(resultObject)); } job.setLastUpdated(DateUtil.currentGMTTime()); _jobDao.update(jobId, job); @@ -732,7 +732,7 @@ public class AsyncJobManagerImpl extends ManagerBase implements AsyncJobManager, } private static String getSerializedErrorMessage(String errorMessage) { - return ApiSerializerHelper.toSerializedStringOld(getResetResultResponse(errorMessage)); + return ApiSerializerHelper.toSerializedString(getResetResultResponse(errorMessage)); } @Override http://git-wip-us.apache.org/repos/asf/cloudstack/blob/86053cd8/server/src/com/cloud/async/AsyncJobResult.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/async/AsyncJobResult.java b/server/src/com/cloud/async/AsyncJobResult.java index 4c37929..280780c 100644 --- a/server/src/com/cloud/async/AsyncJobResult.java +++ b/server/src/com/cloud/async/AsyncJobResult.java @@ -91,7 +91,7 @@ public class AsyncJobResult { } public void setResultObject(Object result) { - this.result = ApiSerializerHelper.toSerializedStringOld(result); + this.result = ApiSerializerHelper.toSerializedString(result); } @Override http://git-wip-us.apache.org/repos/asf/cloudstack/blob/86053cd8/server/src/com/cloud/vm/VirtualMachineManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index eed54af..70fed43 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -597,6 +597,17 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac return advanceStart(vm, params, caller, account, null); } + public <T extends VMInstanceVO> T advanceStartNew(T vm, Map<VirtualMachineProfile.Param, Object> params, User caller, Account account, DeploymentPlan planToDeploy) + throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { + VirtualMachineGuru<T> vmGuru = getVmGuru(vm); + vm = vmGuru.findById(vm.getId()); + + ServiceOfferingVO offering = _offeringDao.findById(vm.getServiceOfferingId()); + VMTemplateVO template = _templateDao.findById(vm.getTemplateId()); + + return vm; + } + @Override public <T extends VMInstanceVO> T advanceStart(T vm, Map<VirtualMachineProfile.Param, Object> params, User caller, Account account, DeploymentPlan planToDeploy) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/86053cd8/server/src/com/cloud/vm/VmWork.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/vm/VmWork.java b/server/src/com/cloud/vm/VmWork.java new file mode 100644 index 0000000..8af7739 --- /dev/null +++ b/server/src/com/cloud/vm/VmWork.java @@ -0,0 +1,54 @@ +// 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 com.cloud.vm; + +public class VmWork { + long userId; + long accountId; + long vmId; + + // VirtualMachineManagerImpl's method name that the work will be handled in the manager + // it should be unique in the implementation class + String targetMethodName; + + public VmWork() { + } + + public long getUserId() { + return userId; + } + + public void setUserId(long userId) { + this.userId = userId; + } + + public long getAccountId() { + return accountId; + } + + public void setAccountId(long accountId) { + this.accountId = accountId; + } + + public long getVmId() { + return vmId; + } + + public void setVmId(long vmId) { + this.vmId = vmId; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/86053cd8/server/src/com/cloud/vm/VmWorkJobDispatcher.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/vm/VmWorkJobDispatcher.java b/server/src/com/cloud/vm/VmWorkJobDispatcher.java new file mode 100644 index 0000000..bd31dd9 --- /dev/null +++ b/server/src/com/cloud/vm/VmWorkJobDispatcher.java @@ -0,0 +1,58 @@ +// 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 com.cloud.vm; + +import javax.inject.Inject; + +import com.cloud.api.ApiSerializerHelper; +import com.cloud.async.AsyncJob; +import com.cloud.async.AsyncJobDispatcher; +import com.cloud.async.AsyncJobManager; +import com.cloud.async.AsyncJobResult; +import com.cloud.user.AccountVO; +import com.cloud.user.UserContext; +import com.cloud.user.dao.AccountDao; +import com.cloud.utils.component.AdapterBase; + +public class VmWorkJobDispatcher extends AdapterBase implements AsyncJobDispatcher { + + @Inject private VirtualMachineManager _vmMgr; + @Inject private AsyncJobManager _asyncJobMgr; + @Inject private AccountDao _accountDao; + + @Override + public void RunJob(AsyncJob job) { + try { + VmWork work = (VmWork)ApiSerializerHelper.fromSerializedString(job.getCmdInfo()); + assert(work != null); + + AccountVO account = _accountDao.findById(work.getAccountId()); + UserContext.registerContext(work.getUserId(), account, null, false); + + try { + + + _asyncJobMgr.completeAsyncJob(job.getId(), AsyncJobResult.STATUS_SUCCEEDED, 0, null); + } finally { + UserContext.unregisterContext(); + } + + } catch(Throwable e) { + _asyncJobMgr.completeAsyncJob(job.getId(), AsyncJobResult.STATUS_FAILED, 0, null); + } + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/86053cd8/server/src/com/cloud/vm/VmWorkStart.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/vm/VmWorkStart.java b/server/src/com/cloud/vm/VmWorkStart.java new file mode 100644 index 0000000..fdc6bfd --- /dev/null +++ b/server/src/com/cloud/vm/VmWorkStart.java @@ -0,0 +1,74 @@ +// 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 com.cloud.vm; + +import java.util.HashMap; +import java.util.Map; + +import com.cloud.api.ApiSerializerHelper; +import com.cloud.deploy.DeploymentPlan; + +public class VmWorkStart extends VmWork { + private DeploymentPlan plan; + + // use serialization friendly map + private Map<String, String> rawParams; + + public VmWorkStart() { + } + + public DeploymentPlan getPlan() { + return plan; + } + + public void setPlan(DeploymentPlan plan) { + this.plan = plan; + } + + public Map<String, String> getRawParams() { + return rawParams; + } + + public void setRawParams(Map<String, String> params) { + this.rawParams = params; + } + + public Map<VirtualMachineProfile.Param, Object> getParams() { + Map<VirtualMachineProfile.Param, Object> map = new HashMap<VirtualMachineProfile.Param, Object>(); + + if(rawParams != null) { + // Strong-typing for VirtualMachineProfile.Param is really over-kill, have to deal with it anyway + for(Map.Entry<String, String> entry : rawParams.entrySet()) { + VirtualMachineProfile.Param key = new VirtualMachineProfile.Param(entry.getKey()); + Object val = ApiSerializerHelper.fromSerializedString(entry.getValue()); + map.put(key, val); + } + } + + return map; + } + + public void setParams( Map<VirtualMachineProfile.Param, Object> params) { + if(params != null) { + rawParams = new HashMap<String, String>(); + for(Map.Entry<VirtualMachineProfile.Param, Object> entry : params.entrySet()) { + rawParams.put(entry.getKey().getName(), ApiSerializerHelper.toSerializedString(entry.getValue())); + } + } + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/86053cd8/server/test/com/cloud/keystore/KeystoreTest.java ---------------------------------------------------------------------- diff --git a/server/test/com/cloud/keystore/KeystoreTest.java b/server/test/com/cloud/keystore/KeystoreTest.java index 47212c1..9ef4c79 100644 --- a/server/test/com/cloud/keystore/KeystoreTest.java +++ b/server/test/com/cloud/keystore/KeystoreTest.java @@ -168,7 +168,7 @@ public class KeystoreTest extends TestCase { vm.setObjectName("virtualmachine"); */ - String result = ApiSerializerHelper.toSerializedStringOld(vm); + String result = ApiSerializerHelper.toSerializedString(vm); // String result = "org.apache.cloudstack.api.response.UserVmResponse/virtualmachine/{\"id\":{\"_tableName\":\"vm_instance\",\"_value\":3},\"name\":\"i-2-3-KY\",\"displayname\":\"i-2-3-KY\",\"account\":\"admin\",\"projectid\":{\"_tableName\":\"projects\"},\"domainid\":{\"_tableName\":\"domain\",\"_value\":1},\"domain\":\"ROOT\",\"created\":\"2011-11-02T21:54:07-0700\",\"state\":\"Running\",\"haenable\":false,\"groupid\":{\"_tableName\":\"instance_group\"},\"zoneid\":{\"_tableName\":\"data_center\",\"_value\":1},\"zonename\":\"KY\",\"hostid\":{\"_tableName\":\"host\",\"_value\":1},\"hostname\":\"xenserver-basic\",\"templateid\":{\"_tableName\":\"vm_template\",\"_value\":2},\"templatename\":\"CentOS 5.3(64-bit) no GUI (XenServer)\",\"templatedisplaytext\":\"CentOS 5.3(64-bit) no GUI (XenServer)\",\"passwordenabled\":false,\"isoid\":{\"_tableName\":\"vm_template\"},\"serviceofferingid\":{\"_tableName\":\"disk_offering\",\"_value\":7},\"serviceofferingname\":\"Small Instance\",\ "cpunumber\":1,\"cpuspeed\":500,\"memory\":512,\"guestosid\":{\"_tableName\":\"guest_os\",\"_value\":12},\"rootdeviceid\":0,\"rootdevicetype\":\"NetworkFilesystem\",\"securitygroup\":[],\"jobid\":{\"_tableName\":\"async_job\"},\"nic\":[{\"id\":7,\"networkid\":200,\"netmask\":\"255.255.255.0\",\"gateway\":\"10.1.1.1\",\"ipaddress\":\"10.1.1.116\",\"isolationuri\":\"vlan://1699\",\"broadcasturi\":\"vlan://1699\",\"traffictype\":\"Guest\",\"type\":\"Virtual\",\"isdefault\":true,\"macaddress\":\"02:00:39:a7:00:01\"}],\"hypervisor\":\"XenServer\"}"; System.out.println(result); //Object obj = ApiSerializerHelper.fromSerializedString(result); @@ -177,7 +177,7 @@ public class KeystoreTest extends TestCase { alert.setId("100"); alert.setDescription("Hello"); - result = ApiSerializerHelper.toSerializedStringOld(alert); + result = ApiSerializerHelper.toSerializedString(alert); System.out.println(result); ApiSerializerHelper.fromSerializedString(result); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/86053cd8/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java ---------------------------------------------------------------------- diff --git a/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java b/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java index 322f051..4f882d0 100644 --- a/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java +++ b/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java @@ -40,16 +40,12 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; import org.apache.cloudstack.api.command.user.vm.RestoreVMCmd; -import org.apache.cloudstack.api.command.user.vm.ScaleVMCmd; import org.junit.Test; import org.junit.Before; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.Spy; import static org.mockito.Mockito.*; - - -import java.lang.reflect.Field; import java.util.List; public class VirtualMachineManagerImplTest { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/86053cd8/server/test/com/cloud/vm/VmWorkTest.java ---------------------------------------------------------------------- diff --git a/server/test/com/cloud/vm/VmWorkTest.java b/server/test/com/cloud/vm/VmWorkTest.java new file mode 100644 index 0000000..cbb768a --- /dev/null +++ b/server/test/com/cloud/vm/VmWorkTest.java @@ -0,0 +1,61 @@ +// 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 com.cloud.vm; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + +import junit.framework.TestCase; + +import com.cloud.deploy.DataCenterDeployment; +import com.cloud.deploy.DeploymentPlan; +import com.cloud.deploy.DeploymentPlanner.ExcludeList; +import com.google.gson.Gson; + +public class VmWorkTest extends TestCase { + Gson gson = new Gson(); + + @Test + public void testDeployPlanSerialization() { + DeploymentPlan plan = new DataCenterDeployment(1L); + ExcludeList excludeList = new ExcludeList(); + + excludeList.addCluster(1); + plan.setAvoids(excludeList); + + String json = gson.toJson(plan); + DeploymentPlan planClone = gson.fromJson(json, DataCenterDeployment.class); + Assert.assertTrue(planClone.getDataCenterId() == plan.getDataCenterId()); + } + + @Test + public void testVmWorkStart() { + VmWorkStart work = new VmWorkStart(); + Map<VirtualMachineProfile.Param, Object> params = new HashMap<VirtualMachineProfile.Param, Object>(); + params.put(VirtualMachineProfile.Param.HaTag, "HA"); + params.put(VirtualMachineProfile.Param.ControlNic, new Long(100)); + work.setParams(params); + + VmWorkStart workClone = gson.fromJson(gson.toJson(work), VmWorkStart.class); + Assert.assertTrue(work.getParams().size() == workClone.getParams().size()); + Assert.assertTrue(work.getParams().get(VirtualMachineProfile.Param.HaTag).equals(workClone.getParams().get(VirtualMachineProfile.Param.HaTag))); + + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/86053cd8/utils/src/com/cloud/utils/EnumUtils.java ---------------------------------------------------------------------- diff --git a/utils/src/com/cloud/utils/EnumUtils.java b/utils/src/com/cloud/utils/EnumUtils.java index ecde7e7..62a8c20 100644 --- a/utils/src/com/cloud/utils/EnumUtils.java +++ b/utils/src/com/cloud/utils/EnumUtils.java @@ -39,4 +39,17 @@ public class EnumUtils { } return defaultVal; } + + public static <T extends Enum<T>> T fromString(Class<T> clz, String value) { + assert(clz != null); + + if(value != null) { + try { + return Enum.valueOf(clz, value.trim()); + } catch(IllegalArgumentException ex) { + assert(false); + } + } + return null; + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/86053cd8/utils/src/com/cloud/utils/MethodCapturer.java ---------------------------------------------------------------------- diff --git a/utils/src/com/cloud/utils/MethodCapturer.java b/utils/src/com/cloud/utils/MethodCapturer.java new file mode 100644 index 0000000..f9fe046 --- /dev/null +++ b/utils/src/com/cloud/utils/MethodCapturer.java @@ -0,0 +1,113 @@ +// 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 +// 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 com.cloud.utils; + +import java.lang.reflect.Method; +import java.util.WeakHashMap; + +import net.sf.cglib.proxy.Callback; +import net.sf.cglib.proxy.CallbackFilter; +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +/* + * This helper class provides a way to retrieve Method in a strong-type way. It takes advantage of power of + * Intelligent IDE(Eclipse) in code-editing + * + * DummyImpl dummy = new DummyImpl(); + * MethodCapturer<DummyImpl> capturer = MethodCapturer.capture(dummy); + * Method method = capturer.get(capturer.instance().foo2()); + * + */ +public class MethodCapturer<T> { + + private final static int CACHE_SIZE = 1024; + + private T _instance; + private Method _method; + + private static WeakHashMap<Object, Object> s_cache = new WeakHashMap<Object, Object>(); + + private MethodCapturer() { + } + + @SuppressWarnings("unchecked") + public static <T> MethodCapturer<T> capture(T obj) { + synchronized(s_cache) { + MethodCapturer<T> capturer = (MethodCapturer<T>)s_cache.get(obj); + if(capturer != null) { + return capturer; + } + + final MethodCapturer<T> capturerNew = new MethodCapturer<T>(); + + Enhancer en = new Enhancer(); + en.setSuperclass(obj.getClass()); + en.setCallbacks(new Callback[] { new MethodInterceptor() { + @Override + public Object intercept(Object arg0, Method arg1, Object[] arg2, + MethodProxy arg3) throws Throwable { + capturerNew.setMethod(arg1); + return null; + } + }, + new MethodInterceptor() { + @Override + public Object intercept(Object arg0, Method arg1, Object[] arg2, + MethodProxy arg3) throws Throwable { + return null; + } + } + }); + en.setCallbackFilter(new CallbackFilter() { + public int accept(Method method) { + if (method.getParameterTypes().length == 0 && method.getName().equals("finalize")) { + return 1; + } + return 0; + }} + ); + + ((MethodCapturer<T>)capturerNew).setInstance((T)en.create()); + + // We expect MethodCapturer is only used for singleton objects here, so we only maintain a limited cache + // here + if(s_cache.size() < CACHE_SIZE) { + s_cache.put(obj, capturerNew); + } + + return capturerNew; + } + } + + public T instance() { + return _instance; + } + + private void setInstance(T instance) { + _instance = instance; + } + + public Method get(Object... useless) { + return _method; + } + + private void setMethod(Method method) { + _method = method; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/86053cd8/utils/test/com/cloud/utils/DummyImpl.java ---------------------------------------------------------------------- diff --git a/utils/test/com/cloud/utils/DummyImpl.java b/utils/test/com/cloud/utils/DummyImpl.java index 467d8e2..37ab6ed 100644 --- a/utils/test/com/cloud/utils/DummyImpl.java +++ b/utils/test/com/cloud/utils/DummyImpl.java @@ -25,4 +25,8 @@ public class DummyImpl implements DummyInterface { public void foo() { System.out.println("Basic foo implementation"); } + + public int foo2() { + return 0; + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/86053cd8/utils/test/com/cloud/utils/MethodCatpurerTest.java ---------------------------------------------------------------------- diff --git a/utils/test/com/cloud/utils/MethodCatpurerTest.java b/utils/test/com/cloud/utils/MethodCatpurerTest.java new file mode 100644 index 0000000..b2729bd --- /dev/null +++ b/utils/test/com/cloud/utils/MethodCatpurerTest.java @@ -0,0 +1,37 @@ +// 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 +// 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 com.cloud.utils; + +import java.lang.reflect.Method; + +public class MethodCatpurerTest { + + public MethodCatpurerTest() { + } + + public void MethodCapturerTest() { + DummyImpl dummy = new DummyImpl(); + MethodCapturer<DummyImpl> capturer = MethodCapturer.capture(dummy); + Method method = capturer.get(capturer.instance().foo2()); + + System.out.println("Method name: " + method.getName()); + } + + public static void main(String args[]) { + new MethodCatpurerTest().MethodCapturerTest(); + } +}
