You can test with this PortManager (admin\config-api)
On 7/23/2010 8:34 PM, Tim Quinn wrote:
> I see there is frequent mail traffic on this, which is reassuring!
>
> Is there an ETA for the fix? I have some unrelated changes but I need
> to run deployment cluster devtests before checking in my changes, and
> those tests don't work due (I think) to this problem.
>
> Just trying to plan my work...
>
> Thanks.
>
> - Tim
>
> On Jul 23, 2010, at 1:55 PM, Jennifer Chou wrote:
>
>> You mean the patch below? I ran the ports, instance, and cluster
>> devtests.
>>
>> On 7/23/2010 7:45 PM, Byron Nevins wrote:
>>> Can you try it on devtests and see if it works?
>>>
>>>
>>> On 7/23/2010 11:42 AM, Jennifer Chou wrote:
>>>> ok sounds good. not checking anything in.
>>>>
>>>> On 7/23/2010 7:32 PM, Byron Nevins wrote:
>>>>> I recommend NOT doing this. We should have this ugly code in one
>>>>> and only one place. ServerHelper has those lines now. It just
>>>>> needs to be refactored into another method in ServerHelper where
>>>>> you call it with a Nodes or Node object...
>>>>>
>>>>>
>>>>> On 7/23/2010 10:44 AM, Jennifer Chou wrote:
>>>>>> Here's the patch I was going to checkin. just running ql on it
>>>>>> right now. Let me know if you want me to go ahead with checking in.
>>>>>> I was thinking that since server being created as passed to
>>>>>> PortManager. Then port manager calls the getHost duck typed
>>>>>> method on Server which I think may not have that info yet?
>>>>>> So I removed call to duck typed method server.getHost in PortManager.
>>>>>>
>>>>>> Index: src/main/java/com/sun/enterprise/config/util/PortManager.java
>>>>>> ===================================================================
>>>>>> ---
>>>>>> src/main/java/com/sun/enterprise/config/util/PortManager.java
>>>>>> (revisio
>>>>>> n 39006)
>>>>>> +++
>>>>>> src/main/java/com/sun/enterprise/config/util/PortManager.java
>>>>>> (working
>>>>>> copy)
>>>>>> @@ -38,6 +38,7 @@
>>>>>> import com.sun.enterprise.config.serverbeans.Cluster;
>>>>>> import com.sun.enterprise.config.serverbeans.Config;
>>>>>> import com.sun.enterprise.config.serverbeans.Domain;
>>>>>> +import com.sun.enterprise.config.serverbeans.Node;
>>>>>> import com.sun.enterprise.config.serverbeans.Server;
>>>>>> import com.sun.enterprise.config.serverbeans.SystemProperty;
>>>>>> import com.sun.enterprise.util.ObjectAnalyzer;
>>>>>> @@ -63,12 +64,26 @@
>>>>>> newServer = theNewServer;
>>>>>> domain = theDomain;
>>>>>> serverName = newServer.getName();
>>>>>> - host = newServer.getHost();
>>>>>> + String nodeName = newServer.getNode();
>>>>>> + if (!StringUtils.ok(nodeName))
>>>>>> + throw new
>>>>>> TransactionFailure(Strings.get("PortManager.noNodeSpecified",
>>>>>> serverName));
>>>>>> +
>>>>>> + Node node = domain.getNodeNamed(nodeName);
>>>>>> + if (node == null)
>>>>>> + throw new
>>>>>> TransactionFailure(Strings.get("PortManager.noNode",nodeName));
>>>>>> +
>>>>>> + host = node.getNodeHost();
>>>>>> + // XXX Hack to get around the fact that the default
>>>>>> localhost
>>>>>> + // node entry is malformed
>>>>>> + if (host == null && nodeName.equals("localhost")) {
>>>>>> + host = "localhost";
>>>>>> + }
>>>>>> +
>>>>>> allPorts = new ArrayList<Integer>();
>>>>>> newServerPorts = new ServerPorts(cluster, config,
>>>>>> domain, newServer);
>>>>>>
>>>>>> if (!StringUtils.ok(host))
>>>>>> - throw new
>>>>>> TransactionFailure(Strings.get("PortManager.noHost",serverName));
>>>>>> + throw new
>>>>>> TransactionFailure(Strings.get("PortManager.noHost",nodeName));
>>>>>>
>>>>>> isLocal = NetUtils.IsThisHostLocal(host);
>>>>>>
>>>>>> @@ -249,7 +264,7 @@
>>>>>> private final Server newServer;
>>>>>> private final boolean isLocal;
>>>>>> private final Domain domain;
>>>>>> - private final String host;
>>>>>> + private String host = null;
>>>>>> private final List<Integer> allPorts;
>>>>>> private final List<Server> allServers;
>>>>>> private final List<ServerPorts> serversOnHost;
>>>>>>
>>>>>> Index:
>>>>>> src/main/java/com/sun/enterprise/config/util/LocalStrings.properties
>>>>>> ===================================================================
>>>>>> ---
>>>>>> src/main/java/com/sun/enterprise/config/util/LocalStrings.properties
>>>>>> (revision 39006)
>>>>>> +++
>>>>>> src/main/java/com/sun/enterprise/config/util/LocalStrings.properties
>>>>>> (working copy)
>>>>>> @@ -3,7 +3,9 @@
>>>>>> PortUtils.duplicate_port=Found two system-property elements with
>>>>>> the same port
>>>>>> number ({0}) for {1}.
>>>>>> PortUtils.non_int_port=Found a system-property with a
>>>>>> non-integer port number (
>>>>>> {0}) for {1}.
>>>>>> PortUtils.illegal_port_number=The supplied port number, {0}, for
>>>>>> the server, {1
>>>>>> }, is illegal. Legal values are 0 to {2} inclusive.
>>>>>> -PortManager.noHost=There is no node-agent-ref specified for the
>>>>>> instance {0}.
>>>>>> +PortManager.noNodeSpecified=There is no node specified for the
>>>>>> instance {0}.
>>>>>> +PortManager.noNode=Node {0} does not exist.
>>>>>> +PortManager.noHost=Node host is not specified on node {0}.
>>>>>> PortManager.noFreePort=Can''t locate a free port. None of the
>>>>>> ports between {0
>>>>>> } and {1} are available.
>>>>>>
>>>>>> On 7/23/2010 6:35 PM, Byron Nevins wrote:
>>>>>>> I just changed things last night -- I'll take a look.
>>>>>>>
>>>>>>> Jennifer -- Server.getHostName() on DAS returns null!!! I'll
>>>>>>> fix it...
>>>>>>>
>>>>>>> On 7/23/2010 9:49 AM, Jennifer Chou wrote:
>>>>>>>> working on fix right now.
>>>>>>>>
>>>>>>>> On 7/23/2010 5:39 PM, Tom Mueller wrote:
>>>>>>>>> Yes.
>>>>>>>>> Tom
>>>>>>>>>
>>>>>>>>> On 7/23/2010 11:37 AM, Tim Quinn wrote:
>>>>>>>>>> Hi.
>>>>>>>>>>
>>>>>>>>>> The Hudson admin job is red with (among other things) this
>>>>>>>>>> error when trying to create an instance:
>>>>>>>>>>
>>>>>>>>>> [java] remote failure: Exception while adding the new configuration org.jvnet.hk2.config.TransactionFailure: There is no node-agent-ref specified for the instance in_892228. : org.jvnet.hk2.config.TransactionFailure: There is no node-agent-ref specified for the instance in_892228.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> We are seeing the same error in the deployment devtests in
>>>>>>>>>> trying to create an instance.
>>>>>>>>>> Is someone looking into this?
>>>>>>>>>> - Tim
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>> --
>>>>> Byron Nevins - Oracle Corporation
>>>>> Home: 650-359-1290
>>>>> Cell: 650-784-4123
>>>>> Sierra: 209-295-2188
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: admin-unsubscribe_at_glassfish.dev.java.net
>>>>> For additional commands, e-mail: admin-help_at_glassfish.dev.java.net
>>>>
>>>
>>> --
>>> Byron Nevins - Oracle Corporation
>>> Home: 650-359-1290
>>> Cell: 650-784-4123
>>> Sierra: 209-295-2188
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: admin-unsubscribe_at_glassfish.dev.java.net For
>>> additional commands, e-mail: admin-help_at_glassfish.dev.java.net
>>
>
>
>
> Oracle <http://www.oracle.com>
> Tim Quinn | Principal Member of Technical Staff | +1.847.604.9475
> Oracle GlassFish Engineering
> Lake Forest, IL
>
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at
https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.enterprise.config.util;
import com.sun.enterprise.config.serverbeans.Cluster;
import com.sun.enterprise.config.serverbeans.Config;
import com.sun.enterprise.config.serverbeans.Domain;
import com.sun.enterprise.config.serverbeans.Node;
import com.sun.enterprise.config.serverbeans.Server;
import com.sun.enterprise.config.serverbeans.SystemProperty;
import com.sun.enterprise.util.ObjectAnalyzer;
import com.sun.enterprise.util.StringUtils;
import com.sun.enterprise.util.Utility;
import com.sun.enterprise.util.net.*;
import java.beans.PropertyVetoException;
import java.util.*;
import org.jvnet.hk2.config.TransactionFailure;
/**
* Hiding place for the remarkably complex logic of assigning ports to instances
* GUARANTEE -- the only thing thrown from here is TransactionFailure
* @author Byron Nevins
*/
public final class PortManager {
public PortManager(Cluster cluster, Config config, Domain theDomain, Server theNewServer) throws TransactionFailure {
try {
if (theNewServer == null || theDomain == null)
throw new TransactionFailure(Strings.get("internal.error", "null argument in PortManager constructor"));
newServer = theNewServer;
domain = theDomain;
serverName = newServer.getName();
String nodeName = newServer.getNode();
if (!StringUtils.ok(nodeName))
throw new TransactionFailure(Strings.get("PortManager.noNodeSpecified", serverName));
Node node = domain.getNodeNamed(nodeName);
if (node == null)
throw new TransactionFailure(Strings.get("PortManager.noNode", nodeName));
host = node.getNodeHost();
// XXX Hack to get around the fact that the default localhost
// node entry is malformed
if (host == null && nodeName.equals("localhost")) {
host = "localhost";
}
allPorts = new ArrayList<Integer>();
newServerPorts = new ServerPorts(cluster, config, domain, newServer);
if (!StringUtils.ok(host))
throw new TransactionFailure(Strings.get("PortManager.noHost", nodeName));
isLocal = NetUtils.IsThisHostLocal(host);
allServers = domain.getServers().getServer();
// why all this nonsense? ConcurrentModificationException!!!
for (Iterator<Server> it = allServers.iterator(); it.hasNext();) {
Server curr = it.next();
if (serverName.equals(curr.getName())) {
it.remove();
}
}
serversOnHost = new ArrayList<ServerPorts>();
}
catch (TransactionFailure tf) {
throw tf;
}
catch (Exception e) {
// this Exception will not take just a Throwable. I MUST give a string
throw new TransactionFailure(e.toString(), e);
}
}
public void process() throws TransactionFailure {
try {
// if there are no port system-property's -- no point in going on!
if (newServerPorts.getMap().isEmpty())
return; // all done!
// make sure user-supplied props are not flaky
PortUtils.checkInternalConsistency(newServer);
// create a list of ALL servers running on the same machine
createServerList();
// create a sorted list of every port on every other server on the same machine.
createAllPortsList();
// we have a list of all possible conflicting server ports.
// let's find some unused ports and reassign the variables inside
// the ServerPorts class
Map<String, Integer> reassigned = reassignPorts();
Set<Map.Entry<String, Integer>> entries = reassigned.entrySet();
List<SystemProperty> sps = newServer.getSystemProperty();
for (Map.Entry<String, Integer> entry : entries) {
String name = entry.getKey();
int port = entry.getValue();
changeSystemProperty(sps, name, "" + port); // do not want commas in the int!
}
}
catch (Exception e) {
throw new TransactionFailure(e.toString(), e);
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("PortManager Dump:");
for (ServerPorts sp : serversOnHost)
sb.append(sp).append('\n');
sb.append("All Ports in all other servers on same host: " + allPorts);
return sb.toString();
}
private void createServerList() {
if (isLocal)
createLocalServerList();
else
createRemoteServerList();
}
private void createLocalServerList() {
for (Server server : allServers) {
if (server.isDas())
serversOnHost.add(new ServerPorts(domain, server));
else if (NetUtils.IsThisHostLocal(server.getNode()))
serversOnHost.add(new ServerPorts(domain, server));
}
}
private void createRemoteServerList() {
for (Server server : allServers) {
// no DAS!
if (server.isInstance() && sameHost(server))
serversOnHost.add(new ServerPorts(domain, server));
}
}
private boolean sameHost(Server server) {
return NetUtils.isEqual(server.getNode(), host);
}
private Map<String, Integer> reassignPorts() throws TransactionFailure {
// inefficient, probably a slicker way to do it. Not worth the effort
// there are at most 8 items...
Map<String, Integer> portProps = newServerPorts.getMap();
Map<String, Integer> changedPortProps = new HashMap<String, Integer>();
Set<Map.Entry<String, Integer>> entries = portProps.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
String name = entry.getKey();
Integer num = entry.getValue();
Integer newNum = reassignPort(num);
if (!newNum.equals(num))
changedPortProps.put(name, newNum);
}
return changedPortProps;
}
private Integer reassignPort(Integer num) throws TransactionFailure {
int max = num + 100;
while (num < max) {
num = getNextUnassignedPort(num);
if (isPortFree(num))
return num;
else
++num;
}
throw new TransactionFailure(Strings.get("PortManager.noFreePort"));
}
private Integer getNextUnassignedPort(Integer num) throws TransactionFailure {
int max = num + MAX_PORT_TRIES; // to avoid infinite loop
for (int inum = num; inum < max; inum++) {
if (!allPorts.contains(inum))
return inum;
}
throw new TransactionFailure(Strings.get("PortManager.noFreePort", num, max));
}
private void changeSystemProperty(List<SystemProperty> sps, String name, String port) throws PropertyVetoException, TransactionFailure {
for (SystemProperty sp : sps) {
if (name.equals(sp.getName())) {
sp.setValue(port);
return;
}
}
// does not exist -- let's add one!
SystemProperty sp = newServer.createChild(SystemProperty.class);
sp.setName(name);
sp.setValue(port);
sps.add(sp);
}
private boolean isPortFree(int num) {
if (isLocal)
return NetUtils.isPortFree(num);
return NetUtils.isPortFree(host, num);
}
private void createAllPortsList() {
for (ServerPorts sp : serversOnHost) {
Collection<Integer> ii = sp.getMap().values();
// do not want duplicates!!
for (Integer i : ii)
if (!allPorts.contains(i))
allPorts.add(i);
}
Collections.sort(allPorts);
}
private final String serverName;
private final Server newServer;
private final boolean isLocal;
private final Domain domain;
private String host = null;
private final List<Integer> allPorts;
private final List<Server> allServers;
private final List<ServerPorts> serversOnHost;
private final ServerPorts newServerPorts;
private final boolean checkLivePorts = true;
private static final int MAX_PORT_TRIES = 1100;
}