From 32185d22eb60453a9f4ddaaa1fca6e814f0ccd67 Mon Sep 17 00:00:00 2001 From: frank Date: Tue, 30 Nov 2010 09:23:04 -0800 Subject: [PATCH 1/5] Fix RPM build failed add cloud-jstl-1.2.jar to deps package --- cloud.spec | 1 + debian/cloud-deps.install | 1 + 2 files changed, 2 insertions(+) diff --git a/cloud.spec b/cloud.spec index d46620697a9..8a2afd21e86 100644 --- a/cloud.spec +++ b/cloud.spec @@ -487,6 +487,7 @@ fi %{_javadir}/%{name}-xenserver-5.6.0-1.jar %{_javadir}/%{name}-xmlrpc-common-3.*.jar %{_javadir}/%{name}-xmlrpc-client-3.*.jar +%{_javadir}/%{name}-jstl-1.2.jar %files core %defattr(0644,root,root,0755) diff --git a/debian/cloud-deps.install b/debian/cloud-deps.install index be8604a5cdc..a169016f278 100644 --- a/debian/cloud-deps.install +++ b/debian/cloud-deps.install @@ -15,3 +15,4 @@ /usr/share/java/cloud-xenserver-5.6.0-1.jar /usr/share/java/cloud-xmlrpc-common-3.*.jar /usr/share/java/cloud-xmlrpc-client-3.*.jar +/usr/share/java/cloud-jstl-*.jar From fa9c882d8c028c903ad8fddba25fffedaf24d123 Mon Sep 17 00:00:00 2001 From: Kelven Yang Date: Mon, 29 Nov 2010 16:48:40 -0800 Subject: [PATCH 2/5] Add VMWare hypervisor guru --- client/tomcatconf/components.xml.in | 1 + server/src/com/cloud/hypervisor/KVMGuru.java | 2 +- .../src/com/cloud/hypervisor/VMwareGuru.java | 54 +++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 server/src/com/cloud/hypervisor/VMwareGuru.java diff --git a/client/tomcatconf/components.xml.in b/client/tomcatconf/components.xml.in index 1eca3242fec..71461e0e30f 100755 --- a/client/tomcatconf/components.xml.in +++ b/client/tomcatconf/components.xml.in @@ -64,6 +64,7 @@ + diff --git a/server/src/com/cloud/hypervisor/KVMGuru.java b/server/src/com/cloud/hypervisor/KVMGuru.java index 32527dc5b88..ccbe4e0a27e 100644 --- a/server/src/com/cloud/hypervisor/KVMGuru.java +++ b/server/src/com/cloud/hypervisor/KVMGuru.java @@ -13,6 +13,7 @@ import com.cloud.vm.VirtualMachineProfile; @Local(value=HypervisorGuru.class) public class KVMGuru extends HypervisorGuruBase implements HypervisorGuru { @Inject GuestOSDao _guestOsDao; + @Override public HypervisorType getHypervisorType() { return HypervisorType.KVM; @@ -33,5 +34,4 @@ public class KVMGuru extends HypervisorGuruBase implements HypervisorGuru { return to; } - } diff --git a/server/src/com/cloud/hypervisor/VMwareGuru.java b/server/src/com/cloud/hypervisor/VMwareGuru.java new file mode 100644 index 00000000000..fb7f90d189a --- /dev/null +++ b/server/src/com/cloud/hypervisor/VMwareGuru.java @@ -0,0 +1,54 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +package com.cloud.hypervisor; + +import javax.ejb.Local; + +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.GuestOSVO; +import com.cloud.storage.dao.GuestOSDao; +import com.cloud.template.VirtualMachineTemplate.BootloaderType; +import com.cloud.utils.component.Inject; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineProfile; + +@Local(value=HypervisorGuru.class) +public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { + @Inject GuestOSDao _guestOsDao; + + protected VMwareGuru() { + super(); + } + + @Override + public HypervisorType getHypervisorType() { + return HypervisorType.VmWare; + } + + @Override + public VirtualMachineTO implement(VirtualMachineProfile vm) { + VirtualMachineTO to = toVirtualMachineTO(vm); + to.setBootloader(BootloaderType.HVM); + + // Determine the VM's OS description + GuestOSVO guestOS = _guestOsDao.findById(vm.getVirtualMachine().getGuestOSId()); + to.setOs(guestOS.getDisplayName()); + return to; + } +} From 54f177cacc2ef206259732b23d0fd8e68199ebc1 Mon Sep 17 00:00:00 2001 From: Kelven Yang Date: Tue, 30 Nov 2010 09:40:35 -0800 Subject: [PATCH 3/5] 1) Make generic dao be able to persist UTF-8 string for internationalization support 2) Undo gson Unicode escape in API response object to avoid double escaping which can break Javascript from getting correct text content 3) Correct API layer in dealing with character encoding 4) Remove double escape in cloud.core.js --- core/.classpath | 2 +- server/.classpath | 4 +- server/src/com/cloud/api/ApiGsonHelper.java | 1 + server/src/com/cloud/api/ApiServer.java | 14 +++--- server/src/com/cloud/api/ApiServlet.java | 12 ++--- .../api/response/ApiResponseSerializer.java | 19 ++++++-- .../cloud/servlet/ConsoleProxyServlet.java | 7 +-- ui/scripts/cloud.core.js | 4 +- .../com/cloud/utils/db/GenericDaoBase.java | 44 +++++++++++++++++-- 9 files changed, 77 insertions(+), 30 deletions(-) diff --git a/core/.classpath b/core/.classpath index 17a6103c14d..1867836084a 100644 --- a/core/.classpath +++ b/core/.classpath @@ -11,7 +11,6 @@ - @@ -39,5 +38,6 @@ + diff --git a/server/.classpath b/server/.classpath index 8a0c5b39e0c..fe6302cf152 100644 --- a/server/.classpath +++ b/server/.classpath @@ -13,13 +13,13 @@ - - + + diff --git a/server/src/com/cloud/api/ApiGsonHelper.java b/server/src/com/cloud/api/ApiGsonHelper.java index 9877d27bdba..4e11d4b1977 100644 --- a/server/src/com/cloud/api/ApiGsonHelper.java +++ b/server/src/com/cloud/api/ApiGsonHelper.java @@ -14,3 +14,4 @@ public class ApiGsonHelper { return s_gBuilder; } } + diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 7613b6db72a..0120fbf02c5 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -274,9 +274,9 @@ public class ApiServer implements HttpRequestHandler { response.setStatusCode(se.getErrorCode()); response.setReasonPhrase(se.getDescription()); BasicHttpEntity body = new BasicHttpEntity(); - body.setContentType("text/xml; charset=UTF-8"); + body.setContentType("text/xml"); String responseStr = ""+se.getErrorCode()+" : "+se.getDescription()+""; - body.setContent(new ByteArrayInputStream(responseStr.getBytes())); + body.setContent(new ByteArrayInputStream(responseStr.getBytes("UTF-8"))); response.setEntity(body); sb.append(" " + se.getErrorCode() + " " + responseStr.length()); @@ -714,19 +714,19 @@ public class ApiServer implements HttpRequestHandler { BasicHttpEntity body = new BasicHttpEntity(); if (BaseCmd.RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { // JSON response - body.setContentType("text/javascript; charset=UTF-8"); + body.setContentType("text/javascript"); if (responseText == null) { - body.setContent(new ByteArrayInputStream("{ \"error\" : { \"description\" : \"Internal Server Error\" } }".getBytes())); + body.setContent(new ByteArrayInputStream("{ \"error\" : { \"description\" : \"Internal Server Error\" } }".getBytes("UTF-8"))); } } else { - body.setContentType("text/xml; charset=UTF-8"); + body.setContentType("text/xml"); if (responseText == null) { - body.setContent(new ByteArrayInputStream("Internal Server Error".getBytes())); + body.setContent(new ByteArrayInputStream("Internal Server Error".getBytes("UTF-8"))); } } if (responseText != null) { - body.setContent(new ByteArrayInputStream(responseText.getBytes())); + body.setContent(new ByteArrayInputStream(responseText.getBytes("UTF-8"))); } resp.setEntity(body); } catch (Exception ex) { diff --git a/server/src/com/cloud/api/ApiServlet.java b/server/src/com/cloud/api/ApiServlet.java index 1e6e87eba11..0ba8243be90 100755 --- a/server/src/com/cloud/api/ApiServlet.java +++ b/server/src/com/cloud/api/ApiServlet.java @@ -320,14 +320,10 @@ public class ApiServlet extends HttpServlet { } else { resp.setContentType("text/xml"); } - resp.setStatus(isError? HttpServletResponse.SC_INTERNAL_SERVER_ERROR : HttpServletResponse.SC_OK); - byte[] respBytes = response.getBytes(); - resp.setContentLength(respBytes.length); - OutputStream os = resp.getOutputStream(); - os.write(respBytes); - os.flush(); - os.close(); - resp.flushBuffer(); + resp.setStatus(isError? HttpServletResponse.SC_INTERNAL_SERVER_ERROR : HttpServletResponse.SC_OK); + + // use getWriter() instead of manually manipulate encoding to have better localization support + resp.getWriter().print(response); } catch (IOException ioex) { if (s_logger.isTraceEnabled()) { s_logger.trace("exception writing response: " + ioex); diff --git a/server/src/com/cloud/api/response/ApiResponseSerializer.java b/server/src/com/cloud/api/response/ApiResponseSerializer.java index ca1852eaaf6..85e60baa3d6 100644 --- a/server/src/com/cloud/api/response/ApiResponseSerializer.java +++ b/server/src/com/cloud/api/response/ApiResponseSerializer.java @@ -4,10 +4,10 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.ArrayList; import java.util.Date; -import java.util.LinkedList; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.apache.log4j.Logger; @@ -28,6 +28,16 @@ public class ApiResponseSerializer { return toXMLSerializedString(result); } } + + private static final Pattern s_unicodeEscapePattern = Pattern.compile("\\\\u([0-9A-Fa-f]{4})"); + public static String unescape(String escaped) { + String str = escaped; + Matcher matcher = s_unicodeEscapePattern.matcher(str); + while(matcher.find()) { + str = str.replaceAll("\\" + matcher.group(0), Character.toString((char)Integer.parseInt(matcher.group(1), 16))); + } + return str; + } private static String toJSONSerializedString(ResponseObject result) { if (result != null) { @@ -39,10 +49,12 @@ public class ApiResponseSerializer { List responses = ((ListResponse)result).getResponses(); if ((responses != null) && !responses.isEmpty()) { int count = responses.size(); - String jsonStr = gson.toJson(responses.get(0)); + String jsonStr = gson.toJson(responses.get(0));; + jsonStr = unescape(jsonStr); sb.append("{ \"" + responses.get(0).getObjectName() + "\" : [ " + jsonStr); for (int i = 1; i < count; i++) { jsonStr = gson.toJson(responses.get(i)); + jsonStr = unescape(jsonStr); sb.append(", " + jsonStr); } sb.append(" ] }"); @@ -54,6 +66,7 @@ public class ApiResponseSerializer { } else { String jsonStr = gson.toJson(result); if ((jsonStr != null) && !"".equals(jsonStr)) { + jsonStr = unescape(jsonStr); if (result instanceof AsyncJobResponse || result instanceof CreateCmdResponse) { sb.append(jsonStr); } else { diff --git a/server/src/com/cloud/servlet/ConsoleProxyServlet.java b/server/src/com/cloud/servlet/ConsoleProxyServlet.java index b43bae7fdb7..7876a343a2b 100644 --- a/server/src/com/cloud/servlet/ConsoleProxyServlet.java +++ b/server/src/com/cloud/servlet/ConsoleProxyServlet.java @@ -66,15 +66,16 @@ public class ConsoleProxyServlet extends HttpServlet { } @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) { + protected void doGet(HttpServletRequest req, HttpServletResponse resp) { + try { String userId = null; String account = null; Account accountObj = null; - + Map params = new HashMap(); params.putAll(req.getParameterMap()); - + HttpSession session = req.getSession(false); if(session == null) { if(verifyRequest(params)) { diff --git a/ui/scripts/cloud.core.js b/ui/scripts/cloud.core.js index fff1902cc93..aa0637821d1 100644 --- a/ui/scripts/cloud.core.js +++ b/ui/scripts/cloud.core.js @@ -537,11 +537,11 @@ function createURL(url) { } function fromdb(val) { - return sanitizeXSS(unescape(noNull(val))); + return sanitizeXSS(noNull(val)); } function todb(val) { - return encodeURIComponent(escape(val)); + return encodeURIComponent(val); } var midmenuItemCount = 20; diff --git a/utils/src/com/cloud/utils/db/GenericDaoBase.java b/utils/src/com/cloud/utils/db/GenericDaoBase.java index dfa6d72c78a..a5dab05daa9 100755 --- a/utils/src/com/cloud/utils/db/GenericDaoBase.java +++ b/utils/src/com/cloud/utils/db/GenericDaoBase.java @@ -18,6 +18,7 @@ package com.cloud.utils.db; import java.io.Serializable; +import java.io.UnsupportedEncodingException; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; @@ -448,7 +449,20 @@ public abstract class GenericDaoBase implements Gene try { final Class type = field.getType(); if (type == String.class) { - field.set(entity, rs.getString(index)); + byte[] bytes = rs.getBytes(index); + if(bytes != null) { + try { + field.set(entity, new String(bytes, "UTF-8")); + } catch (IllegalArgumentException e) { + assert(false); + throw new CloudRuntimeException("IllegalArgumentException when converting UTF-8 data"); + } catch (UnsupportedEncodingException e) { + assert(false); + throw new CloudRuntimeException("UnsupportedEncodingException when converting UTF-8 data"); + } + } else { + field.set(entity, null); + } } else if (type == long.class) { field.setLong(entity, rs.getLong(index)); } else if (type == Long.class) { @@ -560,7 +574,16 @@ public abstract class GenericDaoBase implements Gene @DB(txn=false) @SuppressWarnings("unchecked") protected M getObject(Class type, ResultSet rs, int index) throws SQLException { if (type == String.class) { - return (M)rs.getString(index); + byte[] bytes = rs.getBytes(index); + if(bytes != null) { + try { + return (M)new String(bytes, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new CloudRuntimeException("UnsupportedEncodingException exception while converting UTF-8 data"); + } + } else { + return (M)null; + } } else if (type == int.class) { return (M)new Integer(rs.getInt(index)); } else if (type == Integer.class) { @@ -1197,10 +1220,23 @@ public abstract class GenericDaoBase implements Gene final Column column = attr.field.getAnnotation(Column.class); final int length = column != null ? column.length() : 255; + // to support generic localization, utilize MySql UTF-8 support if (length < str.length()) { - pstmt.setString(j, str.substring(0, column.length())); + try { + pstmt.setBytes(j, str.substring(0, column.length()).getBytes("UTF-8")); + } catch (UnsupportedEncodingException e) { + // no-way it can't support UTF-8 encoding + assert(false); + throw new CloudRuntimeException("UnsupportedEncodingException when saving string as UTF-8 data"); + } } else { - pstmt.setString(j, str); + try { + pstmt.setBytes(j, str.getBytes("UTF-8")); + } catch (UnsupportedEncodingException e) { + // no-way it can't support UTF-8 encoding + assert(false); + throw new CloudRuntimeException("UnsupportedEncodingException when saving string as UTF-8 data"); + } } } else if (attr.field.getType() == Date.class) { final Date date = (Date)value; From 1aee7561841e619306de65b4ae67a5c16a26b5d0 Mon Sep 17 00:00:00 2001 From: abhishek Date: Tue, 30 Nov 2010 10:05:32 -0800 Subject: [PATCH 4/5] bug 7345: During the expunge operation, we were not calling the deleteipforwardingrule method, for a rule which was static nat. Adding that logic. Also, making a change in the domr script as we do not need to execute a line on deletion of a rule status 7345: resolved fixed --- patches/systemvm/debian/config/root/firewall.sh | 2 -- server/src/com/cloud/vm/UserVmManagerImpl.java | 12 +++++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/patches/systemvm/debian/config/root/firewall.sh b/patches/systemvm/debian/config/root/firewall.sh index 2def133e108..494361057a2 100755 --- a/patches/systemvm/debian/config/root/firewall.sh +++ b/patches/systemvm/debian/config/root/firewall.sh @@ -91,8 +91,6 @@ add_one_to_one_nat_entry() { if [ "$op" == "-A" ] then iptables -P FORWARD DROP - else - iptables -P FORWARD ACCEPT fi iptables $op FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT iptables $op FORWARD -i eth2 -o eth0 -d $guestIp -m state --state NEW -j ACCEPT diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index af6470c4100..d370f975d08 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -2245,9 +2245,15 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, VirtualM { if((publicIp.getAccountId().longValue() == vm.getAccountId())) { - _networkMgr.deletePortForwardingRule(rule.getId(),true);//delete the rule with the sys user's credentials - if(s_logger.isDebugEnabled()) - s_logger.debug("Rule "+rule.getId()+" for vm:"+vm.getHostName()+" is deleted successfully during expunge operation"); + if(publicIp.isOneToOneNat()){ + _networkMgr.deleteIpForwardingRule(rule.getId()); + if(s_logger.isDebugEnabled()) + s_logger.debug("Rule "+rule.getId()+" for vm:"+vm.getHostName()+" is deleted successfully during expunge operation"); + }else{ + _networkMgr.deletePortForwardingRule(rule.getId(),true);//delete the rule with the sys user's credentials + if(s_logger.isDebugEnabled()) + s_logger.debug("Rule "+rule.getId()+" for vm:"+vm.getHostName()+" is deleted successfully during expunge operation"); + } } } } From 5c8619903b3ba3f9951866b01cd9369e1396d849 Mon Sep 17 00:00:00 2001 From: alena Date: Tue, 30 Nov 2010 10:14:44 -0800 Subject: [PATCH 5/5] bug 7342: return ipaddress instead of publicip in listIpForwardingRules/listPortForwardingRules api responses. status 7342: resolved fixed --- api/src/com/cloud/api/response/FirewallRuleResponse.java | 2 +- api/src/com/cloud/api/response/IpForwardingRuleResponse.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api/src/com/cloud/api/response/FirewallRuleResponse.java b/api/src/com/cloud/api/response/FirewallRuleResponse.java index 1c98d3d5d90..96e02f12976 100644 --- a/api/src/com/cloud/api/response/FirewallRuleResponse.java +++ b/api/src/com/cloud/api/response/FirewallRuleResponse.java @@ -43,7 +43,7 @@ public class FirewallRuleResponse extends BaseResponse { @SerializedName("virtualmachinedisplayname") @Param(description="the VM display name for the port forwarding rule") private String virtualMachineDisplayName; - @SerializedName("publicipaddress") @Param(description="the public ip address for the port forwarding rule") + @SerializedName("ipaddress") @Param(description="the public ip address for the port forwarding rule") private String publicIpAddress; public Long getId() { diff --git a/api/src/com/cloud/api/response/IpForwardingRuleResponse.java b/api/src/com/cloud/api/response/IpForwardingRuleResponse.java index 648562b219a..45aaa6e0e4d 100644 --- a/api/src/com/cloud/api/response/IpForwardingRuleResponse.java +++ b/api/src/com/cloud/api/response/IpForwardingRuleResponse.java @@ -43,7 +43,7 @@ public class IpForwardingRuleResponse extends BaseResponse { @SerializedName("virtualmachinedisplayname") @Param(description="the VM display name for the port forwarding rule") private String virtualMachineDisplayName; - @SerializedName("publicipaddress") @Param(description="the public ip address for the port forwarding rule") + @SerializedName("ipaddress") @Param(description="the public ip address for the port forwarding rule") private String publicIpAddress; public Long getId() {