improve the clouds machine namer make it an interface, move to sub-package, give good javadoc, and make the methods a little bit more intuitive.
fixes problems that CustomMachineNamer wasn't actually being invoked anymore since we called in via groups! all the salting (unique id) stuff is a little confused, because different jclouds providers seem to do it in different ways. Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/8008df4f Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/8008df4f Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/8008df4f Branch: refs/heads/master Commit: 8008df4f2da54bc13bf373c6179cb889e165eec7 Parents: fa09efc Author: Alex Heneveld <[email protected]> Authored: Fri May 8 14:01:49 2015 +0100 Committer: Alex Heneveld <[email protected]> Committed: Fri May 8 18:51:49 2015 +0100 ---------------------------------------------------------------------- .../location/cloud/CloudLocationConfig.java | 6 +- .../location/cloud/CloudMachineNamer.java | 169 ------------------- .../location/cloud/CustomMachineNamer.java | 72 -------- .../cloud/names/AbstractCloudMachineNamer.java | 149 ++++++++++++++++ .../cloud/names/BasicCloudMachineNamer.java | 91 ++++++++++ .../location/cloud/names/CloudMachineNamer.java | 61 +++++++ .../cloud/names/CustomMachineNamer.java | 72 ++++++++ .../location/cloud/CloudMachineNamerTest.java | 45 ++--- .../location/cloud/CustomMachineNamerTest.java | 7 +- .../location/jclouds/JcloudsLocation.java | 10 +- .../location/jclouds/JcloudsLocationConfig.java | 1 + .../location/jclouds/JcloudsMachineNamer.java | 11 +- .../location/jclouds/JcloudsLocationTest.java | 8 +- .../jclouds/JcloudsMachineNamerTest.java | 10 +- .../entity/service/InitdServiceInstaller.java | 4 +- 15 files changed, 430 insertions(+), 286 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8008df4f/core/src/main/java/brooklyn/location/cloud/CloudLocationConfig.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/location/cloud/CloudLocationConfig.java b/core/src/main/java/brooklyn/location/cloud/CloudLocationConfig.java index 5aad7bd..39ef6fa 100644 --- a/core/src/main/java/brooklyn/location/cloud/CloudLocationConfig.java +++ b/core/src/main/java/brooklyn/location/cloud/CloudLocationConfig.java @@ -59,7 +59,11 @@ public interface CloudLocationConfig { // default is just shy of common 64-char boundary (could perhaps increase slightly...) public static final ConfigKey<Integer> VM_NAME_MAX_LENGTH = ConfigKeys.newIntegerConfigKey( - "vmNameMaxLength", "Maximum length of VM name", 61); + "vmNameMaxLength", "Maximum length of VM name", 61); + + public static final ConfigKey<Integer> VM_NAME_SALT_LENGTH = ConfigKeys.newIntegerConfigKey( + "vmNameSaltLength", "Number of characters to use for a random identifier inserted in hostname " + + "to uniquely identify machines", 4); public static final ConfigKey<String> WAIT_FOR_SSHABLE = ConfigKeys.newStringConfigKey("waitForSshable", "Whether and how long to wait for a newly provisioned VM to be accessible via ssh; " + http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8008df4f/core/src/main/java/brooklyn/location/cloud/CloudMachineNamer.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/location/cloud/CloudMachineNamer.java b/core/src/main/java/brooklyn/location/cloud/CloudMachineNamer.java deleted file mode 100644 index 5200a1c..0000000 --- a/core/src/main/java/brooklyn/location/cloud/CloudMachineNamer.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.location.cloud; - -import brooklyn.entity.Application; -import brooklyn.entity.Entity; -import brooklyn.entity.trait.HasShortName; -import brooklyn.util.config.ConfigBag; -import brooklyn.util.text.Identifiers; -import brooklyn.util.text.StringShortener; -import brooklyn.util.text.Strings; - -import com.google.common.base.CharMatcher; - -public class CloudMachineNamer { - - protected final ConfigBag setup; - int defaultMachineNameMaxLength = CloudLocationConfig.VM_NAME_MAX_LENGTH.getDefaultValue(); - int nameInGroupReservedLength = 9; - - public CloudMachineNamer(ConfigBag setup) { - this.setup = setup; - } - - public String generateNewMachineUniqueName() { - return generateNewIdReservingLength(0); - } - - public String generateNewMachineUniqueNameFromGroupId(String groupId) { - int suffixLength = getMaxNameLength() - (groupId.length() + 1); // +1 for the hyphen - if (suffixLength <= 0) { - return groupId; - } - - return groupId + "-" + Identifiers.makeRandomId(Math.min(4, suffixLength)); - } - - public String generateNewGroupId() { - return generateNewIdReservingLength(nameInGroupReservedLength); - } - - protected String generateNewIdReservingLength(int lengthToReserve) { - Object context = setup.peek(CloudLocationConfig.CALLER_CONTEXT); - Entity entity = null; - if (context instanceof Entity) entity = (Entity) context; - - StringShortener shortener = Strings.shortener().separator("-"); - shortener.append("system", "brooklyn"); - - // randId often not necessary, as an 8-char hex identifier is added later (in jclouds? can we override?) - // however it can be useful to have this early in the string, to prevent collisions in places where it is abbreviated - shortener.append("randId", Identifiers.makeRandomId(4)); - - String user = System.getProperty("user.name"); - if (!"brooklyn".equals(user)) - // include user; unless the user is 'brooklyn', as 'brooklyn-brooklyn-' is just silly! - shortener.append("user", user); - - if (entity!=null) { - Application app = entity.getApplication(); - if (app!=null) { - shortener.append("app", shortName(app)) - .append("appId", app.getId()); - } - shortener.append("entity", shortName(entity)) - .append("entityId", entity.getId()); - } else if (context!=null) { - shortener.append("context", context.toString()); - } - - shortener.truncate("user", 12) - .truncate("app", 16) - .truncate("entity", 16) - .truncate("appId", 4) - .truncate("entityId", 4) - .truncate("context", 12); - - shortener.canTruncate("user", 8) - .canTruncate("app", 5) - .canTruncate("entity", 5) - .canTruncate("system", 2) - .canTruncate("app", 3) - .canTruncate("entity", 3) - .canRemove("app") - .canTruncate("user", 4) - .canRemove("entity") - .canTruncate("context", 4) - .canTruncate("randId", 2) - .canRemove("user") - .canTruncate("appId", 2) - .canRemove("appId"); - - int len = getMaxNameLength(); - // decrement by e.g. 9 chars because jclouds adds that (dash plus 8 for hex id) - len -= lengthToReserve; - if (len<=0) return ""; - String s = shortener.getStringOfMaxLength(len); - return sanitize(s).toLowerCase(); - } - - /** returns the max length of a VM name for the cloud specified in setup; - * this value is typically decremented by 9 to make room for jclouds labels; - * delegates to {@link #getCustomMaxNameLength()} when - * {@link CloudLocationConfig#VM_NAME_MAX_LENGTH} is not set */ - public int getMaxNameLength() { - if (setup.containsKey(CloudLocationConfig.VM_NAME_MAX_LENGTH)) { - // if a length is set, use that - return setup.get(CloudLocationConfig.VM_NAME_MAX_LENGTH); - } - - Integer custom = getCustomMaxNameLength(); - if (custom!=null) return custom; - - // return the default - return defaultMachineNameMaxLength; - } - - public CloudMachineNamer lengthMaxPermittedForMachineName(int defaultMaxLength) { - this.defaultMachineNameMaxLength = defaultMaxLength; - return this; - } - - /** number of chars to use or reserve for the machine identifier when constructing a group identifier; - * defaults to 9, e.g. a hyphen and 8 random chars which is the jclouds model - * @return */ - public CloudMachineNamer lengthReservedForNameInGroup(int identifierRequiredLength) { - this.nameInGroupReservedLength = identifierRequiredLength; - return this; - } - - /** method for overriding to provide custom logic when an explicit config key is not set */ - public Integer getCustomMaxNameLength() { - return null; - } - - protected String shortName(Object x) { - if (x instanceof HasShortName) { - return ((HasShortName)x).getShortName(); - } - if (x instanceof Entity) { - return ((Entity)x).getDisplayName(); - } - return x.toString(); - } - - public static String sanitize(String s) { - return CharMatcher.inRange('A', 'Z') - .or(CharMatcher.inRange('a', 'z')) - .or(CharMatcher.inRange('0', '9')) - .negate() - .trimAndCollapseFrom(s, '-'); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8008df4f/core/src/main/java/brooklyn/location/cloud/CustomMachineNamer.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/location/cloud/CustomMachineNamer.java b/core/src/main/java/brooklyn/location/cloud/CustomMachineNamer.java deleted file mode 100644 index c818dc9..0000000 --- a/core/src/main/java/brooklyn/location/cloud/CustomMachineNamer.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.location.cloud; - -import java.util.Map; - -import brooklyn.config.ConfigKey; -import brooklyn.entity.Entity; -import brooklyn.entity.basic.ConfigKeys; -import brooklyn.entity.basic.EntityInternal; -import brooklyn.util.config.ConfigBag; -import brooklyn.util.text.Strings; -import brooklyn.util.text.TemplateProcessor; - -import com.google.common.collect.ImmutableMap; -import com.google.common.reflect.TypeToken; - -public class CustomMachineNamer extends CloudMachineNamer { - - public static final ConfigKey<String> MACHINE_NAME_TEMPLATE = ConfigKeys.newStringConfigKey("custom.machine.namer.machine", - "Freemarker template format for custom machine name", "${entity.displayName}"); - @SuppressWarnings("serial") - public static final ConfigKey<Map<String, ?>> EXTRA_SUBSTITUTIONS = ConfigKeys.newConfigKey(new TypeToken<Map<String, ?>>() {}, - "custom.machine.namer.substitutions", "Additional substitutions to be used in the template", ImmutableMap.<String, Object>of()); - - public CustomMachineNamer(ConfigBag setup) { - super(setup); - } - - @Override - public String generateNewMachineUniqueName() { - Object context = setup.peek(CloudLocationConfig.CALLER_CONTEXT); - Entity entity = null; - if (context instanceof Entity) { - entity = (Entity) context; - } - - String template = this.setup.get(MACHINE_NAME_TEMPLATE); - - String processed; - if (entity == null) { - processed = TemplateProcessor.processTemplateContents(template, this.setup.get(EXTRA_SUBSTITUTIONS)); - } else { - processed = TemplateProcessor.processTemplateContents(template, (EntityInternal)entity, this.setup.get(EXTRA_SUBSTITUTIONS)); - } - - processed = Strings.removeFromStart(processed, "#ftl\n"); - - return sanitize(processed); - } - - @Override - public String generateNewMachineUniqueNameFromGroupId(String groupId) { - return generateNewMachineUniqueName(); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8008df4f/core/src/main/java/brooklyn/location/cloud/names/AbstractCloudMachineNamer.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/location/cloud/names/AbstractCloudMachineNamer.java b/core/src/main/java/brooklyn/location/cloud/names/AbstractCloudMachineNamer.java new file mode 100644 index 0000000..4e81a46 --- /dev/null +++ b/core/src/main/java/brooklyn/location/cloud/names/AbstractCloudMachineNamer.java @@ -0,0 +1,149 @@ +/* + * 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 brooklyn.location.cloud.names; + +import brooklyn.entity.Entity; +import brooklyn.entity.trait.HasShortName; +import brooklyn.location.cloud.CloudLocationConfig; +import brooklyn.util.config.ConfigBag; +import brooklyn.util.text.Identifiers; +import brooklyn.util.text.Strings; + +import com.google.common.annotations.Beta; +import com.google.common.base.CharMatcher; + +/** + * Implements <b>most</b> of {@link CloudMachineNamer}, + * leaving just one method -- {@link #generateNewIdOfLength(int)} -- + * for subclasses to provide. + * <p> + * {@link CloudLocationConfig#VM_NAME_MAX_LENGTH} is used to find the VM length, + * unless {@link #getCustomMaxNameLength(ConfigBag)} is overridden or + * {@link #setDefaultMachineNameMaxLength(int)} invoked on the instance supplied. + */ +public abstract class AbstractCloudMachineNamer implements CloudMachineNamer { + + int defaultMachineNameMaxLength = CloudLocationConfig.VM_NAME_MAX_LENGTH.getDefaultValue(); + int defaultMachineNameSaltLength = CloudLocationConfig.VM_NAME_SALT_LENGTH.getDefaultValue(); + protected String separator = "-"; + + public String generateNewMachineUniqueName(ConfigBag setup) { + return generateNewIdReservingLength(setup, 0); + } + + public String generateNewMachineUniqueNameFromGroupId(ConfigBag setup, String groupId) { + int availSaltLength = getMaxNameLength(setup) - (groupId.length() + separator.length()); + int requestedSaltLength = getLengthForMachineUniqueNameSalt(setup, false); + if (availSaltLength <= 0 || requestedSaltLength <= 0) { + return groupId; + } + + return sanitize(groupId + separator + Identifiers.makeRandomId(Math.min(requestedSaltLength, availSaltLength))).toLowerCase(); + } + + public String generateNewGroupId(ConfigBag setup) { + return sanitize(generateNewIdReservingLength(setup, getLengthForMachineUniqueNameSalt(setup, true))).toLowerCase(); + } + + protected String generateNewIdReservingLength(ConfigBag setup, int lengthToReserve) { + int len = getMaxNameLength(setup); + // decrement by e.g. 9 chars because jclouds adds that (dash plus 8 for hex id) + len -= lengthToReserve; + if (len<=0) return ""; + return Strings.maxlen(generateNewIdOfLength(setup, len), len); + } + + /** Method for subclasses to provide to construct the context-specific part of an identifier, + * for use in {@link #generateNewGroupId()} and {@link #generateNewMachineUniqueName()}. + * + * @param maxLengthHint an indication of the maximum length permitted for the ID generated, + * supplied for implementations which wish to use this information to decide what to truncate. + * (This class will truncate any return values longer than this.) + */ + protected abstract String generateNewIdOfLength(ConfigBag setup, int maxLengthHint); + + /** Returns the max length of a VM name for the cloud specified in setup; + * this value is typically decremented by 9 to make room for jclouds labels; + * delegates to {@link #getCustomMaxNameLength()} when + * {@link CloudLocationConfig#VM_NAME_MAX_LENGTH} is not set */ + public int getMaxNameLength(ConfigBag setup) { + if (setup.containsKey(CloudLocationConfig.VM_NAME_MAX_LENGTH)) { + // if a length is set explicitly, use that (but intercept default behaviour) + return setup.get(CloudLocationConfig.VM_NAME_MAX_LENGTH); + } + + Integer custom = getCustomMaxNameLength(setup); + if (custom!=null) return custom; + + // return the default + return defaultMachineNameMaxLength; + } + + public int getLengthForMachineUniqueNameSalt(ConfigBag setup, boolean includeSeparator) { + int saltLen; + if (setup.containsKey(CloudLocationConfig.VM_NAME_SALT_LENGTH)) { + saltLen = setup.get(CloudLocationConfig.VM_NAME_SALT_LENGTH); + } else { + // default value comes from key, but custom default can be set + saltLen = defaultMachineNameSaltLength; + } + + if (saltLen>0 && includeSeparator) + saltLen += separator.length(); + + return saltLen; + } + + public AbstractCloudMachineNamer setDefaultMachineNameMaxLength(int defaultMaxLength) { + this.defaultMachineNameMaxLength = defaultMaxLength; + return this; + } + + /** Number of chars to use or reserve for the machine identifier when constructing a group identifier; + * jclouds for instance uses "-" plus 8 */ + public AbstractCloudMachineNamer setDefaultMachineNameSeparatorAndSaltLength(String separator, int defaultMachineUniqueNameSaltLength) { + this.separator = separator; + this.defaultMachineNameSaltLength = defaultMachineUniqueNameSaltLength; + return this; + } + + /** Method for overriding to provide custom logic when an explicit config key is not set for the machine length. */ + public Integer getCustomMaxNameLength(ConfigBag setup) { + return null; + } + + protected static String shortName(Object x) { + if (x instanceof HasShortName) { + return ((HasShortName)x).getShortName(); + } + if (x instanceof Entity) { + return ((Entity)x).getDisplayName(); + } + return x.toString(); + } + + @Beta //probably won't live here long-term + public static String sanitize(String s) { + return CharMatcher.inRange('A', 'Z') + .or(CharMatcher.inRange('a', 'z')) + .or(CharMatcher.inRange('0', '9')) + .negate() + .trimAndCollapseFrom(s, '-'); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8008df4f/core/src/main/java/brooklyn/location/cloud/names/BasicCloudMachineNamer.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/location/cloud/names/BasicCloudMachineNamer.java b/core/src/main/java/brooklyn/location/cloud/names/BasicCloudMachineNamer.java new file mode 100644 index 0000000..626a7ea --- /dev/null +++ b/core/src/main/java/brooklyn/location/cloud/names/BasicCloudMachineNamer.java @@ -0,0 +1,91 @@ +/* + * 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 brooklyn.location.cloud.names; + +import brooklyn.entity.Application; +import brooklyn.entity.Entity; +import brooklyn.location.cloud.CloudLocationConfig; +import brooklyn.util.config.ConfigBag; +import brooklyn.util.text.Identifiers; +import brooklyn.util.text.StringShortener; +import brooklyn.util.text.Strings; + +/** + * Standard implementation of {@link CloudMachineNamer}, + * which looks at several of the properties of the context (entity) + * and is clever about abbreviating them. */ +public class BasicCloudMachineNamer extends AbstractCloudMachineNamer { + + @Override + protected String generateNewIdOfLength(ConfigBag setup, int len) { + Object context = setup.peek(CloudLocationConfig.CALLER_CONTEXT); + Entity entity = null; + if (context instanceof Entity) entity = (Entity) context; + + StringShortener shortener = Strings.shortener().separator("-"); + shortener.append("system", "brooklyn"); + + // randId often not necessary, as an 8-char hex identifier is added later (in jclouds? can we override?) + // however it can be useful to have this early in the string, to prevent collisions in places where it is abbreviated + shortener.append("randId", Identifiers.makeRandomId(4)); + + String user = System.getProperty("user.name"); + if (!"brooklyn".equals(user)) + // include user; unless the user is 'brooklyn', as 'brooklyn-brooklyn-' is just silly! + shortener.append("user", user); + + if (entity!=null) { + Application app = entity.getApplication(); + if (app!=null) { + shortener.append("app", shortName(app)) + .append("appId", app.getId()); + } + shortener.append("entity", shortName(entity)) + .append("entityId", entity.getId()); + } else if (context!=null) { + shortener.append("context", context.toString()); + } + + shortener.truncate("user", 12) + .truncate("app", 16) + .truncate("entity", 16) + .truncate("appId", 4) + .truncate("entityId", 4) + .truncate("context", 12); + + shortener.canTruncate("user", 8) + .canTruncate("app", 5) + .canTruncate("entity", 5) + .canTruncate("system", 2) + .canTruncate("app", 3) + .canTruncate("entity", 3) + .canRemove("app") + .canTruncate("user", 4) + .canRemove("entity") + .canTruncate("context", 4) + .canTruncate("randId", 2) + .canRemove("user") + .canTruncate("appId", 2) + .canRemove("appId"); + + String s = shortener.getStringOfMaxLength(len); + return sanitize(s).toLowerCase(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8008df4f/core/src/main/java/brooklyn/location/cloud/names/CloudMachineNamer.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/location/cloud/names/CloudMachineNamer.java b/core/src/main/java/brooklyn/location/cloud/names/CloudMachineNamer.java new file mode 100644 index 0000000..022c1f4 --- /dev/null +++ b/core/src/main/java/brooklyn/location/cloud/names/CloudMachineNamer.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 brooklyn.location.cloud.names; + +import brooklyn.entity.Entity; +import brooklyn.location.Location; +import brooklyn.location.cloud.CloudLocationConfig; +import brooklyn.util.config.ConfigBag; + +/** + * Interface used to construct names for individual cloud machines and for groups of machines. + * <p> + * Implementations <b>must</b> provide a constructor which takes a single argument, + * being the {@link ConfigBag} for the context where the machine is being created + * (usually a {@link Location}). + * <p> + * With that bag, the config key {@link CloudLocationConfig#CALLER_CONTEXT} + * typically contains the {@link Entity} for which the machine is being created. + */ +public interface CloudMachineNamer { + + /** + * Generate a name for a new machine, based on context. + * <p> + * The name should normally be unique, as a context might produce multiple machines, + * for example basing it partially on information from the context but also including some random salt. + */ + public String generateNewMachineUniqueName(ConfigBag setup); + /** + * Generate a name stem for a group of machines, based on context. + * <p> + * The name does not need to be unique, as uniqueness will be applied by {@link #generateNewMachineUniqueNameFromGroupId(String)}. + */ + public String generateNewGroupId(ConfigBag setup); + + /** + * Generate a unique name from the given name stem. + * <p> + * The name stem is normally based on context information so the usual + * function of this method is to apply a suffix which helps to uniquely distinguish between machines + * in cases where the same name stem ({@link #generateNewGroupId()}) is used for multiple machines. + */ + public String generateNewMachineUniqueNameFromGroupId(ConfigBag setup, String groupId); + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8008df4f/core/src/main/java/brooklyn/location/cloud/names/CustomMachineNamer.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/location/cloud/names/CustomMachineNamer.java b/core/src/main/java/brooklyn/location/cloud/names/CustomMachineNamer.java new file mode 100644 index 0000000..9fde17e --- /dev/null +++ b/core/src/main/java/brooklyn/location/cloud/names/CustomMachineNamer.java @@ -0,0 +1,72 @@ +/* + * 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 brooklyn.location.cloud.names; + +import java.util.Map; + +import brooklyn.config.ConfigKey; +import brooklyn.entity.Entity; +import brooklyn.entity.basic.ConfigKeys; +import brooklyn.entity.basic.EntityInternal; +import brooklyn.location.cloud.CloudLocationConfig; +import brooklyn.util.config.ConfigBag; +import brooklyn.util.text.Strings; +import brooklyn.util.text.TemplateProcessor; + +import com.google.common.collect.ImmutableMap; +import com.google.common.reflect.TypeToken; + +/** Provides a machine namer which looks at a location config key {@link #MACHINE_NAME_TEMPLATE} + * to construct the hostname. + * For instance, setting this to <code>${config.entity_hostname}</code> + * will take the hostname from an <code>entity_hostname</code> key passed as entity <code>brooklyn.config</code>. + * <p> + * Note that this is not jclouds aware, so jclouds-specific cloud max lengths are not observed with this class. + */ +public class CustomMachineNamer extends BasicCloudMachineNamer { + + public static final ConfigKey<String> MACHINE_NAME_TEMPLATE = ConfigKeys.newStringConfigKey("custom.machine.namer.machine", + "Freemarker template format for custom machine name", "${entity.displayName}"); + @SuppressWarnings("serial") + public static final ConfigKey<Map<String, ?>> EXTRA_SUBSTITUTIONS = ConfigKeys.newConfigKey(new TypeToken<Map<String, ?>>() {}, + "custom.machine.namer.substitutions", "Additional substitutions to be used in the template", ImmutableMap.<String, Object>of()); + + @Override + protected String generateNewIdOfLength(ConfigBag setup, int len) { + Object context = setup.peek(CloudLocationConfig.CALLER_CONTEXT); + Entity entity = null; + if (context instanceof Entity) { + entity = (Entity) context; + } + + String template = setup.get(MACHINE_NAME_TEMPLATE); + + String processed; + if (entity == null) { + processed = TemplateProcessor.processTemplateContents(template, setup.get(EXTRA_SUBSTITUTIONS)); + } else { + processed = TemplateProcessor.processTemplateContents(template, (EntityInternal)entity, setup.get(EXTRA_SUBSTITUTIONS)); + } + + processed = Strings.removeFromStart(processed, "#ftl\n"); + + return sanitize(processed); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8008df4f/core/src/test/java/brooklyn/location/cloud/CloudMachineNamerTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/brooklyn/location/cloud/CloudMachineNamerTest.java b/core/src/test/java/brooklyn/location/cloud/CloudMachineNamerTest.java index 4da08bc..0bff9d0 100644 --- a/core/src/test/java/brooklyn/location/cloud/CloudMachineNamerTest.java +++ b/core/src/test/java/brooklyn/location/cloud/CloudMachineNamerTest.java @@ -30,6 +30,9 @@ import org.testng.annotations.Test; import brooklyn.entity.basic.ApplicationBuilder; import brooklyn.entity.basic.Entities; import brooklyn.entity.proxying.EntitySpec; +import brooklyn.location.cloud.names.AbstractCloudMachineNamer; +import brooklyn.location.cloud.names.BasicCloudMachineNamer; +import brooklyn.location.cloud.names.CloudMachineNamer; import brooklyn.test.entity.LocalManagementContextForTests; import brooklyn.test.entity.TestApplication; import brooklyn.test.entity.TestEntity; @@ -54,7 +57,7 @@ public class CloudMachineNamerTest { ConfigBag cfg = new ConfigBag() .configure(CloudLocationConfig.CALLER_CONTEXT, child); - String result = new CloudMachineNamer(cfg).generateNewGroupId(); + String result = new BasicCloudMachineNamer().generateNewGroupId(cfg); log.info("test entity child group id gives: "+result); // e.g. brooklyn-alex-tistapp-uube-testent-xisg-rwad @@ -75,10 +78,10 @@ public class CloudMachineNamerTest { ConfigBag cfg = new ConfigBag() .configure(CloudLocationConfig.CALLER_CONTEXT, child); - CloudMachineNamer namer = new CloudMachineNamer(cfg); + BasicCloudMachineNamer namer = new BasicCloudMachineNamer(); - String result = namer.generateNewMachineUniqueName(); - Assert.assertTrue(result.length() <= namer.getMaxNameLength()); + String result = namer.generateNewMachineUniqueName(cfg); + Assert.assertTrue(result.length() <= namer.getMaxNameLength(cfg)); String user = Strings.maxlen(System.getProperty("user.name"), 4).toLowerCase(); Assert.assertTrue(result.indexOf(user) >= 0); Assert.assertTrue(result.indexOf("-tistapp-") >= 0); @@ -94,10 +97,10 @@ public class CloudMachineNamerTest { ConfigBag cfg = new ConfigBag() .configure(CloudLocationConfig.CALLER_CONTEXT, child); - CloudMachineNamer namer = new CloudMachineNamer(cfg); + CloudMachineNamer namer = new BasicCloudMachineNamer(); - String groupId = namer.generateNewGroupId(); - String result = namer.generateNewMachineUniqueNameFromGroupId(groupId); + String groupId = namer.generateNewGroupId(cfg); + String result = namer.generateNewMachineUniqueNameFromGroupId(cfg, groupId); Assert.assertTrue(result.startsWith(groupId)); Assert.assertTrue(result.length() == groupId.length() + 5); } @@ -109,24 +112,28 @@ public class CloudMachineNamerTest { ConfigBag cfg = new ConfigBag() .configure(CloudLocationConfig.CALLER_CONTEXT, child); - CloudMachineNamer namer = new CloudMachineNamer(cfg); - namer.lengthMaxPermittedForMachineName(10); - String result = namer.generateNewMachineUniqueName(); + BasicCloudMachineNamer namer = new BasicCloudMachineNamer(); + namer.setDefaultMachineNameMaxLength(10); + String result = namer.generateNewMachineUniqueName(cfg); Assert.assertEquals(result.length(), 10); } @Test - public void testLengthReserverdForNameInGroup() { + public void testLengthReservedForNameInGroup() { app = ApplicationBuilder.newManagedApp(EntitySpec.create(TestApplication.class).displayName("TistApp"), LocalManagementContextForTests.newInstance()); TestEntity child = app.createAndManageChild(EntitySpec.create(TestEntity.class).displayName("TestEnt")); ConfigBag cfg = new ConfigBag() .configure(CloudLocationConfig.CALLER_CONTEXT, child); - CloudMachineNamer namer = new CloudMachineNamer(cfg); - namer.lengthMaxPermittedForMachineName(10); - namer.lengthReservedForNameInGroup(4); - String groupId = namer.generateNewGroupId(); - Assert.assertEquals(5, groupId.length(), "groupId="+groupId); + BasicCloudMachineNamer namer = new BasicCloudMachineNamer(); + namer.setDefaultMachineNameMaxLength(20); + namer.setDefaultMachineNameSeparatorAndSaltLength(":I", 5); + String groupId = namer.generateNewGroupId(cfg); + Assert.assertEquals(13, groupId.length(), "groupId="+groupId); + String machineId = namer.generateNewMachineUniqueNameFromGroupId(cfg, groupId); + Assert.assertEquals(20, machineId.length(), "machineId="+machineId); + // separator is not sanitized -- caller should know what they are doing there! + Assert.assertTrue(machineId.startsWith(groupId+"-i"), "machineId="+machineId); } @Test @@ -136,9 +143,9 @@ public class CloudMachineNamerTest { ConfigBag cfg = new ConfigBag() .configure(CloudLocationConfig.CALLER_CONTEXT, child); - CloudMachineNamer namer = new CloudMachineNamer(cfg); + CloudMachineNamer namer = new BasicCloudMachineNamer(); - String result = namer.generateNewMachineUniqueName(); + String result = namer.generateNewMachineUniqueName(cfg); assertTrue(result.indexOf("t-ap") >= 0, "result="+result); for (int c : "_%$()\r\n\t[]*.!".getBytes()) { assertFalse(result.contains(new String(new char [] {(char)c})), "result="+result); @@ -147,7 +154,7 @@ public class CloudMachineNamerTest { @Test public void testSanitize() { - Assert.assertEquals(CloudMachineNamer.sanitize( + Assert.assertEquals(AbstractCloudMachineNamer.sanitize( "me & you like alphanumeric but not _ or !!! or dots...dots...dots %$()\r\n\t[]*etc"), "me-you-like-alphanumeric-but-not-or-or-dots-dots-dots-etc"); } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8008df4f/core/src/test/java/brooklyn/location/cloud/CustomMachineNamerTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/brooklyn/location/cloud/CustomMachineNamerTest.java b/core/src/test/java/brooklyn/location/cloud/CustomMachineNamerTest.java index 829edb4..322acd1 100644 --- a/core/src/test/java/brooklyn/location/cloud/CustomMachineNamerTest.java +++ b/core/src/test/java/brooklyn/location/cloud/CustomMachineNamerTest.java @@ -26,6 +26,7 @@ import org.testng.annotations.Test; import brooklyn.entity.basic.ApplicationBuilder; import brooklyn.entity.basic.Entities; import brooklyn.entity.proxying.EntitySpec; +import brooklyn.location.cloud.names.CustomMachineNamer; import brooklyn.test.entity.LocalManagementContextForTests; import brooklyn.test.entity.TestApplication; import brooklyn.test.entity.TestEntity; @@ -55,21 +56,21 @@ public class CustomMachineNamerTest { @Test public void testMachineNameNoConfig() { config.configure(CloudLocationConfig.CALLER_CONTEXT, child); - Assert.assertEquals(new CustomMachineNamer(config).generateNewMachineUniqueName(), "TestEnt"); + Assert.assertEquals(new CustomMachineNamer().generateNewMachineUniqueName(config), "TestEnt"); } @Test public void testMachineNameWithConfig() { child.setSequenceValue(999); config.configure(CustomMachineNamer.MACHINE_NAME_TEMPLATE, "number${entity.sequenceValue}"); - Assert.assertEquals(new CustomMachineNamer(config).generateNewMachineUniqueName(), "number999"); + Assert.assertEquals(new CustomMachineNamer().generateNewMachineUniqueName(config), "number999"); } @Test public void testMachineNameWithExtraSubstitutions() { config.configure(CustomMachineNamer.MACHINE_NAME_TEMPLATE, "foo-${fooName}-bar-${barName}-baz-${bazName.substitution}") .configure(CustomMachineNamer.EXTRA_SUBSTITUTIONS, ImmutableMap.of("fooName", "foo", "barName", "bar", "bazName", this)); - Assert.assertEquals(new CustomMachineNamer(config).generateNewMachineUniqueName(), "foo-foo-bar-bar-baz-baz"); + Assert.assertEquals(new CustomMachineNamer().generateNewMachineUniqueName(config), "foo-foo-bar-bar-baz-baz"); } public String getSubstitution() { http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8008df4f/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java index 45019d5..1e1dccf 100644 --- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java +++ b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java @@ -108,7 +108,7 @@ import brooklyn.location.basic.LocationConfigUtils.OsCredential; import brooklyn.location.basic.SshMachineLocation; import brooklyn.location.cloud.AbstractCloudMachineProvisioningLocation; import brooklyn.location.cloud.AvailabilityZoneExtension; -import brooklyn.location.cloud.CloudMachineNamer; +import brooklyn.location.cloud.names.CloudMachineNamer; import brooklyn.location.jclouds.JcloudsPredicates.NodeInLocation; import brooklyn.location.jclouds.networking.JcloudsPortForwarderExtension; import brooklyn.location.jclouds.templates.PortableTemplateBuilder; @@ -321,14 +321,14 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im protected CloudMachineNamer getCloudMachineNamer(ConfigBag config) { String namerClass = config.get(LocationConfigKeys.CLOUD_MACHINE_NAMER_CLASS); if (Strings.isNonBlank(namerClass)) { - Optional<CloudMachineNamer> cloudNamer = Reflections.invokeConstructorWithArgs(getManagementContext().getCatalogClassLoader(), namerClass, config); + Optional<CloudMachineNamer> cloudNamer = Reflections.invokeConstructorWithArgs(getManagementContext().getCatalogClassLoader(), namerClass); if (cloudNamer.isPresent()) { return cloudNamer.get(); } else { throw new IllegalStateException("Failed to create CloudMachineNamer "+namerClass+" for location "+this); } } else { - return new JcloudsMachineNamer(config); + return new JcloudsMachineNamer(); } } @@ -565,7 +565,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im final ComputeService computeService = getConfig(COMPUTE_SERVICE_REGISTRY).findComputeService(setup, true); CloudMachineNamer cloudMachineNamer = getCloudMachineNamer(setup); - String groupId = elvis(setup.get(GROUP_ID), cloudMachineNamer.generateNewGroupId()); + String groupId = elvis(setup.get(GROUP_ID), cloudMachineNamer.generateNewGroupId(setup)); NodeMetadata node = null; JcloudsSshMachineLocation sshMachineLocation = null; @@ -609,7 +609,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im setup.getUnusedConfig()); templateTimestamp = Duration.of(provisioningStopwatch); - template.getOptions().getUserMetadata().put("Name", cloudMachineNamer.generateNewMachineUniqueNameFromGroupId(groupId)); + template.getOptions().getUserMetadata().put("Name", cloudMachineNamer.generateNewMachineUniqueNameFromGroupId(setup, groupId)); nodes = computeService.createNodesInGroup(groupId, 1, template); provisionTimestamp = Duration.of(provisioningStopwatch); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8008df4f/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocationConfig.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocationConfig.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocationConfig.java index b7b61a7..3e03837 100644 --- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocationConfig.java +++ b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocationConfig.java @@ -250,6 +250,7 @@ public interface JcloudsLocationConfig extends CloudLocationConfig { "Registry/Factory for creating jclouds ComputeService; default is almost always fine, except where tests want to customize behaviour", ComputeServiceRegistryImpl.INSTANCE); + @SuppressWarnings("serial") public static final ConfigKey<Map<String,String>> TEMPLATE_OPTIONS = ConfigKeys.newConfigKey( new TypeToken<Map<String, String>>() {}, "templateOptions", "Additional jclouds template options"); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8008df4f/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsMachineNamer.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsMachineNamer.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsMachineNamer.java index c3f7b28..301ed43 100644 --- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsMachineNamer.java +++ b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsMachineNamer.java @@ -18,18 +18,15 @@ */ package brooklyn.location.jclouds; -import brooklyn.location.cloud.CloudMachineNamer; +import brooklyn.location.cloud.names.BasicCloudMachineNamer; import brooklyn.util.config.ConfigBag; -public class JcloudsMachineNamer extends CloudMachineNamer { - - public JcloudsMachineNamer(ConfigBag setup) { - super(setup); - } +public class JcloudsMachineNamer extends BasicCloudMachineNamer { + @Override /** returns the max length of a VM name for the cloud specified in setup; * this value is typically decremented by 9 to make room for jclouds labels */ - public Integer getCustomMaxNameLength() { + public Integer getCustomMaxNameLength(ConfigBag setup) { // otherwise, for some known clouds which only allow a short name, use that length if ("vcloud".equals( setup.peek(JcloudsLocationConfig.CLOUD_PROVIDER) )) return 24; http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8008df4f/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsLocationTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsLocationTest.java b/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsLocationTest.java index 60aec22..b133457 100644 --- a/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsLocationTest.java +++ b/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsLocationTest.java @@ -47,6 +47,7 @@ import brooklyn.entity.basic.Entities; import brooklyn.location.LocationSpec; import brooklyn.location.NoMachinesAvailableException; import brooklyn.location.basic.LocationConfigKeys; +import brooklyn.location.cloud.names.CustomMachineNamer; import brooklyn.location.geo.HostGeoInfo; import brooklyn.location.jclouds.JcloudsLocation.UserCreation; import brooklyn.management.internal.LocalManagementContext; @@ -436,10 +437,10 @@ public class JcloudsLocationTest implements JcloudsLocationConfig { @Test public void testCreateWithCustomMachineNamer() { - final String machineNamerClass = "brooklyn.location.cloud.CustomMachineNamer"; + final String machineNamerClass = CustomMachineNamer.class.getName(); BailOutJcloudsLocation jcloudsLocation = newSampleBailOutJcloudsLocationForTesting(ImmutableMap.of( LocationConfigKeys.CLOUD_MACHINE_NAMER_CLASS, machineNamerClass)); - jcloudsLocation.tryObtainAndCheck(ImmutableMap.of(), new Predicate<ConfigBag>() { + jcloudsLocation.tryObtainAndCheck(ImmutableMap.of(CustomMachineNamer.MACHINE_NAME_TEMPLATE, "ignored"), new Predicate<ConfigBag>() { public boolean apply(ConfigBag input) { Assert.assertEquals(input.get(LocationConfigKeys.CLOUD_MACHINE_NAMER_CLASS), machineNamerClass); return true; @@ -449,9 +450,10 @@ public class JcloudsLocationTest implements JcloudsLocationConfig { @Test public void testCreateWithCustomMachineNamerOnObtain() { - final String machineNamerClass = "brooklyn.location.cloud.CustomMachineNamer"; + final String machineNamerClass = CustomMachineNamer.class.getName(); BailOutJcloudsLocation jcloudsLocation = newSampleBailOutJcloudsLocationForTesting(); jcloudsLocation.tryObtainAndCheck(ImmutableMap.of( + CustomMachineNamer.MACHINE_NAME_TEMPLATE, "ignored", LocationConfigKeys.CLOUD_MACHINE_NAMER_CLASS, machineNamerClass), new Predicate<ConfigBag>() { public boolean apply(ConfigBag input) { Assert.assertEquals(input.get(LocationConfigKeys.CLOUD_MACHINE_NAMER_CLASS), machineNamerClass); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8008df4f/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsMachineNamerTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsMachineNamerTest.java b/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsMachineNamerTest.java index 2a51617..da21750 100644 --- a/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsMachineNamerTest.java +++ b/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsMachineNamerTest.java @@ -36,15 +36,15 @@ public class JcloudsMachineNamerTest { .configure(JcloudsLocationConfig.CLOUD_PROVIDER, "vcloud") .configure(JcloudsLocationConfig.CALLER_CONTEXT, "!mycontext!"); - String result = new JcloudsMachineNamer(cfg).generateNewGroupId(); + String result = new JcloudsMachineNamer().generateNewGroupId(cfg); log.info("test mycontext vcloud group id gives: "+result); - // brooklyn-user-mycontext!-1234 - // br-user-myco-1234 - Assert.assertTrue(result.length() <= 15); + // brooklyn-user-!mycontext!-1234 + // br-<code>-<user>-myco-1234 + Assert.assertTrue(result.length() <= 24-4-1, "result: "+result); String user = Strings.maxlen(System.getProperty("user.name"), 2).toLowerCase(); - // (length 2 will happen if user is brooklyn) + // (length 2 will happen if user is brooklyn, to avoid brooklyn-brooklyn at start!) Assert.assertTrue(result.indexOf(user) >= 0); Assert.assertTrue(result.indexOf("-myc") >= 0); } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8008df4f/software/base/src/main/java/brooklyn/entity/service/InitdServiceInstaller.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/service/InitdServiceInstaller.java b/software/base/src/main/java/brooklyn/entity/service/InitdServiceInstaller.java index ce52038..6586bb1 100644 --- a/software/base/src/main/java/brooklyn/entity/service/InitdServiceInstaller.java +++ b/software/base/src/main/java/brooklyn/entity/service/InitdServiceInstaller.java @@ -32,7 +32,7 @@ import brooklyn.entity.basic.SoftwareProcess; import brooklyn.entity.effector.EffectorTasks; import brooklyn.entity.trait.HasShortName; import brooklyn.location.basic.SshMachineLocation; -import brooklyn.location.cloud.CloudMachineNamer; +import brooklyn.location.cloud.names.AbstractCloudMachineNamer; import brooklyn.management.Task; import brooklyn.policy.Enricher; import brooklyn.util.ResourceUtils; @@ -112,7 +112,7 @@ public class InitdServiceInstaller implements SystemServiceInstaller { } else { name = "brooklyn-service"; } - return CloudMachineNamer.sanitize(name.toString()).toLowerCase(); + return AbstractCloudMachineNamer.sanitize(name.toString()).toLowerCase(); } private String getStartScriptName() {
