You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by cl...@apache.org on 2022/11/04 04:13:46 UTC

[activemq-artemis] branch main updated: ARTEMIS-4081 Upgrade command

This is an automated email from the ASF dual-hosted git repository.

clebertsuconic pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/activemq-artemis.git


The following commit(s) were added to refs/heads/main by this push:
     new 9c88fb4f88 ARTEMIS-4081 Upgrade command
9c88fb4f88 is described below

commit 9c88fb4f88ce1827d470ceee832e2efb4f5b3980
Author: Clebert Suconic <cl...@apache.org>
AuthorDate: Fri Oct 7 11:44:40 2022 -0400

    ARTEMIS-4081 Upgrade command
    
    This command will help updating the instance from a previous home
---
 .../org/apache/activemq/artemis/cli/Artemis.java   |   3 +-
 .../activemq/artemis/cli/commands/Create.java      | 220 +++++-------------
 .../artemis/cli/commands/InstallAbstract.java      | 176 ++++++++++++++
 .../apache/activemq/artemis/cli/commands/Run.java  |  18 ++
 .../activemq/artemis/cli/commands/Upgrade.java     | 237 +++++++++++++++++++
 .../artemis/cli/commands/bin/artemis-service.xml   |   4 +-
 .../artemis/cli/commands/etc/artemis.profile       |   2 +-
 .../artemis/cli/commands/etc/artemis.profile.cmd   |   2 +-
 .../artemis/maven/ArtemisUpgradePlugin.java        | 120 ++++++++++
 docs/user-manual/en/upgrading.md                   |  28 ++-
 docs/user-manual/en/versions.md                    |   2 +
 tests/smoke-tests/pom.xml                          |  39 ++++
 .../servers/toUpgradeETC/artemis-roles.properties  |  18 ++
 .../servers/toUpgradeETC/artemis-users.properties  |  18 ++
 .../servers/toUpgradeETC}/artemis.profile          |  20 +-
 .../servers/toUpgradeETC/bootstrap.xml             |  39 ++++
 .../servers/toUpgradeETC/broker.xml                | 254 +++++++++++++++++++++
 .../servers/toUpgradeETC/jolokia-access.xml        |  35 +++
 .../servers/toUpgradeETC/logging.properties        |  90 ++++++++
 .../servers/toUpgradeETC/login.config              |  29 +++
 .../servers/toUpgradeETC/management.xml            |  52 +++++
 .../servers/toUpgradeTest/bin/artemis              |  24 ++
 .../servers/toUpgradeTest/bin/artemis-service      | 158 +++++++++++++
 .../servers/windows}/bin/artemis-service.xml       |  20 +-
 .../servers/windows/bin/artemis.cmd                |  76 ++++++
 .../servers/windowsETC/artemis-roles.properties    |  18 ++
 .../servers/windowsETC/artemis-users.properties    |  18 ++
 .../servers/windowsETC}/artemis.profile.cmd        |  16 +-
 .../servers/windowsETC/bootstrap.xml               |  39 ++++
 .../servers/windowsETC/broker.xml                  | 254 +++++++++++++++++++++
 .../servers/windowsETC/jolokia-access.xml          |  35 +++
 .../servers/windowsETC/logging.properties          |  90 ++++++++
 .../servers/windowsETC/login.config                |  29 +++
 .../servers/windowsETC/management.xml              |  52 +++++
 .../smoke/upgradeTest/CompareUpgradeTest.java      | 145 ++++++++++++
 .../tests/smoke/upgradeTest/UpgradeTest.java       |  72 ++++++
 36 files changed, 2250 insertions(+), 202 deletions(-)

diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java
index f58e56dcf0..31bd72ffd6 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java
@@ -32,6 +32,7 @@ import org.apache.activemq.artemis.cli.commands.InvalidOptionsError;
 import org.apache.activemq.artemis.cli.commands.Kill;
 import org.apache.activemq.artemis.cli.commands.Mask;
 import org.apache.activemq.artemis.cli.commands.PrintVersion;
+import org.apache.activemq.artemis.cli.commands.Upgrade;
 import org.apache.activemq.artemis.cli.commands.activation.ActivationSequenceSet;
 import org.apache.activemq.artemis.cli.commands.check.HelpCheck;
 import org.apache.activemq.artemis.cli.commands.check.NodeCheck;
@@ -243,7 +244,7 @@ public class Artemis {
       } else {
          builder.withGroup("data").withDescription("data tools group (print|recover) (example ./artemis data print)").
             withDefaultCommand(HelpData.class).withCommands(RecoverMessages.class, PrintData.class);
-         builder = builder.withCommand(Create.class);
+         builder = builder.withCommands(Create.class, Upgrade.class);
       }
 
       return builder;
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java
index 7aa2d7a75f..0e703dec3f 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java
@@ -17,29 +17,18 @@
 
 package org.apache.activemq.artemis.cli.commands;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.io.StringWriter;
-import java.nio.charset.StandardCharsets;
 import java.text.DecimalFormat;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
-import io.airlift.airline.Arguments;
 import io.airlift.airline.Command;
 import io.airlift.airline.Option;
 import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
 import org.apache.activemq.artemis.api.core.RoutingType;
-import org.apache.activemq.artemis.cli.CLIException;
 import org.apache.activemq.artemis.cli.commands.util.HashUtil;
 import org.apache.activemq.artemis.cli.commands.util.SyncCalculation;
 import org.apache.activemq.artemis.core.server.JournalType;
@@ -52,7 +41,7 @@ import org.apache.activemq.artemis.utils.FileUtil;
  * CLI action that creates a broker instance directory.
  */
 @Command(name = "create", description = "creates a new broker instance")
-public class Create extends InputAbstract {
+public class Create extends InstallAbstract {
 
    private static final Integer DEFAULT_PORT = 61616;
 
@@ -73,13 +62,17 @@ public class Create extends InputAbstract {
     *  This is to make sure maven or something else is not hiding these resources.
     *  ********************************************************************************** */
 
-   public static final String BIN_ARTEMIS_CMD = "bin/artemis.cmd";
+   public static final String ARTEMIS_CMD = "artemis.cmd";
+   public static final String BIN_ARTEMIS_CMD = "bin/" + ARTEMIS_CMD;
    public static final String BIN_ARTEMIS_SERVICE_EXE = "bin/artemis-service.exe";
    public static final String BIN_ARTEMIS_SERVICE_EXE_CONFIG = "bin/artemis-service.exe.config";
-   public static final String BIN_ARTEMIS_SERVICE_XML = "bin/artemis-service.xml";
+   public static final String ARTEMIS_SERVICE_XML = "artemis-service.xml";
+   public static final String BIN_ARTEMIS_SERVICE_XML = "bin/" + ARTEMIS_SERVICE_XML;
    public static final String ETC_ARTEMIS_PROFILE_CMD = "artemis.profile.cmd";
-   public static final String BIN_ARTEMIS = "bin/artemis";
-   public static final String BIN_ARTEMIS_SERVICE = "bin/artemis-service";
+   public static final String ARTEMIS = "artemis";
+   public static final String BIN_ARTEMIS = "bin/" + ARTEMIS;
+   public static final String ARTEMIS_SERVICE = "artemis-service";
+   public static final String BIN_ARTEMIS_SERVICE = "bin/" + ARTEMIS_SERVICE;
    public static final String ETC_ARTEMIS_PROFILE = "artemis.profile";
    public static final String ETC_LOG4J2_PROPERTIES = "log4j2.properties";
    public static final String ETC_BOOTSTRAP_XML = "bootstrap.xml";
@@ -115,9 +108,6 @@ public class Create extends InputAbstract {
    public static final String ETC_PAGE_SYNC_SETTINGS = "etc/page-sync-settings.txt";
    public static final String ETC_JOLOKIA_ACCESS_XML = "jolokia-access.xml";
 
-   @Arguments(description = "The instance directory to hold the broker's configuration and data.  Path must be writable.", required = true)
-   private File directory;
-
    @Option(name = "--host", description = "The host name of the broker (Default: 0.0.0.0 or input if clustered)")
    private String host;
 
@@ -160,15 +150,9 @@ public class Create extends InputAbstract {
    @Option(name = "--force", description = "Overwrite configuration at destination directory")
    private boolean force;
 
-   @Option(name = "--home", description = "Directory where ActiveMQ Artemis is installed")
-   private File home;
-
    @Option(name = "--data", description = "Directory where ActiveMQ data are stored. Paths can be absolute or relative to artemis.instance directory ('data' by default)")
    private String data = "data";
 
-   @Option(name = "--etc", description = "Directory where ActiveMQ configuration is located. Paths can be absolute or relative to artemis.instance directory ('etc' by default)")
-   private String etc = "etc";
-
    @Option(name = "--clustered", description = "Enable clustering")
    private boolean clustered = false;
 
@@ -196,15 +180,6 @@ public class Create extends InputAbstract {
    @Option(name = "--cluster-password", description = "The cluster password to use for clustering. (Default: input)")
    private String clusterPassword = null;
 
-   @Option(name = "--encoding", description = "The encoding that text files should use")
-   private String encoding = "UTF-8";
-
-   @Option(name = "--java-options", description = "Extra java options to be passed to the profile")
-   private String javaOptions = "";
-
-   @Option(name = "--java-memory", description = "Define the -Xmx memory parameter for the broker. Default = '2G'")
-   private String javaMemory = "2G";
-
    @Option(name = "--allow-anonymous", description = "Enables anonymous configuration on security, opposite of --require-login (Default: input)")
    private Boolean allowAnonymous = null;
 
@@ -345,9 +320,6 @@ public class Create extends InputAbstract {
    @Option(name = "--jdbc-lock-expiration", description = "Lock expiration")
    long jdbcLockExpiration = ActiveMQDefaultConfiguration.getDefaultJdbcLockExpirationMillis();
 
-   private boolean IS_WINDOWS;
-   private boolean IS_CYGWIN;
-
    private boolean isAutoCreate() {
       if (autoCreate == null) {
          if (noAutoCreate != null) {
@@ -362,14 +334,6 @@ public class Create extends InputAbstract {
       return autoCreate;
    }
 
-   public File getInstance() {
-      return directory;
-   }
-
-   public void setInstance(File directory) {
-      this.directory = directory;
-   }
-
    public String getHost() {
       if (host == null) {
          host = "0.0.0.0";
@@ -397,13 +361,6 @@ public class Create extends InputAbstract {
       this.force = force;
    }
 
-   public File getHome() {
-      if (home == null) {
-         home = new File(getBrokerHome());
-      }
-      return home;
-   }
-
    public void setHome(File home) {
       this.home = home;
    }
@@ -420,14 +377,6 @@ public class Create extends InputAbstract {
       return sharedStore;
    }
 
-   public String getEncoding() {
-      return encoding;
-   }
-
-   public void setEncoding(String encoding) {
-      this.encoding = encoding;
-   }
-
    public String getData() {
       return data;
    }
@@ -553,13 +502,6 @@ public class Create extends InputAbstract {
       return run(context);
    }
 
-   /**
-    * This method is made public for the testsuite
-    */
-   public InputStream openStream(String source) {
-      return this.getClass().getResourceAsStream(source);
-   }
-
    /**
     * Checks that the directory provided either exists and is writable or doesn't exist but can be created.
     */
@@ -583,10 +525,9 @@ public class Create extends InputAbstract {
       return directory;
    }
 
+   @Override
    public Object run(ActionContext context) throws Exception {
-
-      IS_WINDOWS = System.getProperty("os.name").toLowerCase().trim().startsWith("win");
-      IS_CYGWIN = IS_WINDOWS && "cygwin".equals(System.getenv("OSTYPE"));
+      super.run(context);
 
       setupJournalType();
 
@@ -670,7 +611,6 @@ public class Create extends InputAbstract {
       filters.put("${message-load-balancing}", messageLoadBalancing.toString());
       filters.put("${user}", getUser());
       filters.put("${password}", getPassword());
-      filters.put("${role}", role);
       filters.put("${encoded.role}", role.replaceAll(" ", "\\\\ "));
 
 
@@ -749,30 +689,21 @@ public class Create extends InputAbstract {
       if (home != null) {
          filters.put("${home}", path(home));
       }
-      filters.put("${artemis.home}", path(getHome().toString()));
-      filters.put("${artemis.instance}", path(directory));
-      filters.put("${artemis.instance.uri}", directory.toURI().toString());
-      filters.put("${artemis.instance.uri.windows}", directory.toURI().toString().replaceAll("%", "%%"));
-      filters.put("${artemis.instance.name}", directory.getName());
-      filters.put("${java.home}", path(System.getProperty("java.home")));
 
       new File(directory, "bin").mkdirs();
       File etcFolder = createDirectory(etc, directory);
-      filters.put("${artemis.instance.etc.uri}", etcFolder.toURI().toString());
-      filters.put("${artemis.instance.etc.uri.windows}", etcFolder.toURI().toString().replaceAll("%", "%%"));
-      filters.put("${artemis.instance.etc}", path(etcFolder));
-      File logFolder = createDirectory("log", directory);
-      File oomeDumpFile = new File(logFolder, "oom_dump.hprof");
-      filters.put("${artemis.instance.oome.dump}", path(oomeDumpFile));
       new File(directory, "tmp").mkdirs();
       new File(directory, "lib").mkdirs();
       File dataFolder = createDirectory(data, directory);
-      filters.put("${artemis.instance.data}", path(dataFolder));
+      File logFolder = createDirectory("log", directory);
+      File oomeDumpFile = new File(logFolder, "oom_dump.hprof");
 
       if (javaOptions == null || javaOptions.length() == 0) {
          javaOptions = "";
       }
 
+      addScriptFilters(filters, getHome(), getInstance(), etcFolder, dataFolder, oomeDumpFile, javaMemory, javaOptions, role);
+
       boolean allowAnonymous = isAllowAnonymous();
 
 
@@ -794,22 +725,21 @@ public class Create extends InputAbstract {
 
       filters.put("${journal-retention}", retentionTag);
 
-
       filters.put("${java-opts}", javaOptions);
       filters.put("${java-memory}", javaMemory);
 
       if (allowAnonymous) {
-         write(ETC_LOGIN_CONFIG_WITH_GUEST, new File(etcFolder, ETC_LOGIN_CONFIG), filters, false);
+         write(ETC_LOGIN_CONFIG_WITH_GUEST, new File(etcFolder, ETC_LOGIN_CONFIG), filters, false, force);
       } else {
-         write(ETC_LOGIN_CONFIG_WITHOUT_GUEST, new File(etcFolder, ETC_LOGIN_CONFIG), filters, false);
+         write(ETC_LOGIN_CONFIG_WITHOUT_GUEST, new File(etcFolder, ETC_LOGIN_CONFIG), filters, false, force);
       }
 
       writeEtc(ETC_ARTEMIS_ROLES_PROPERTIES, etcFolder, filters, false);
 
       if (IS_WINDOWS) {
          write(BIN_ARTEMIS_CMD, filters, false);
-         write(BIN_ARTEMIS_SERVICE_EXE);
-         write(BIN_ARTEMIS_SERVICE_EXE_CONFIG);
+         write(BIN_ARTEMIS_SERVICE_EXE, force);
+         write(BIN_ARTEMIS_SERVICE_EXE_CONFIG, force);
          write(BIN_ARTEMIS_SERVICE_XML, filters, false);
          writeEtc(ETC_ARTEMIS_PROFILE_CMD, etcFolder, filters, false);
       }
@@ -881,7 +811,6 @@ public class Create extends InputAbstract {
       writeEtc(ETC_ARTEMIS_USERS_PROPERTIES, etcFolder, filters, false);
 
       // we want this variable to remain unchanged so that it will use the value set in the profile
-      filters.remove("${artemis.instance}");
       if (SecurityManagerType.getType(securityManager) == SecurityManagerType.BASIC) {
          filters.put("${security-manager-settings}", readTextFile(ETC_BASIC_SECURITY_MANAGER_TXT, filters));
       } else {
@@ -894,7 +823,7 @@ public class Create extends InputAbstract {
          filters.put("${jolokia.options}", "<!-- option relax-jolokia used, so strict-checking will be removed here -->");
       } else {
          filters.put("${jolokia.options}", "<!-- Check for the proper origin on the server side, too -->\n" +
-                     "        <strict-checking/>");
+            "        <strict-checking/>");
       }
       writeEtc(ETC_JOLOKIA_ACCESS_XML, etcFolder, filters, false);
 
@@ -930,6 +859,34 @@ public class Create extends InputAbstract {
       return null;
    }
 
+   protected static void addScriptFilters(HashMap<String, String> filters,
+                          File home,
+                          File directory,
+                          File etcFolder,
+                          File dataFolder,
+                          File oomeDumpFile,
+                          String javaMemory,
+                          String javaOptions,
+                          String role) throws IOException {
+      filters.put("${artemis.home}", path(home));
+      // I am using a different replacing pattern here, for cases where want an actual ${artemis.instance} in the output
+      // so that's just to make a distinction
+      filters.put("@artemis.instance@", path(directory));
+      filters.put("${artemis.instance.uri}", directory.toURI().toString());
+      filters.put("${artemis.instance.uri.windows}", directory.toURI().toString().replaceAll("%", "%%"));
+      filters.put("${artemis.instance.name}", directory.getName());
+      filters.put("${java.home}", path(System.getProperty("java.home")));
+
+      filters.put("${artemis.instance.etc.uri}", etcFolder.toURI().toString());
+      filters.put("${artemis.instance.etc.uri.windows}", etcFolder.toURI().toString().replaceAll("%", "%%"));
+      filters.put("${artemis.instance.etc}", path(etcFolder));
+      filters.put("${artemis.instance.oome.dump}", path(oomeDumpFile));
+      filters.put("${artemis.instance.data}", path(dataFolder));
+      filters.put("${java-memory}", javaMemory);
+      filters.put("${java-opts}", javaOptions);
+      filters.put("${role}", role);
+   }
+
    private String getConnectors(HashMap<String, String> filters) throws IOException {
       if (staticNode != null) {
          StringWriter stringWriter = new StringWriter();
@@ -1069,7 +1026,7 @@ public class Create extends InputAbstract {
                syncFilter.put("${maxaio}", journalType == JournalType.ASYNCIO ? "" + ActiveMQDefaultConfiguration.getDefaultJournalMaxIoAio() : "1");
 
                getActionContext().out.println("done! Your system can make " + writesPerMillisecondStr +
-                                     " writes per millisecond, your journal-buffer-timeout will be " + nanoseconds);
+                                                 " writes per millisecond, your journal-buffer-timeout will be " + nanoseconds);
 
                filters.put("${journal-buffer.settings}", readTextFile(ETC_JOURNAL_BUFFER_SETTINGS, syncFilter));
 
@@ -1140,89 +1097,20 @@ public class Create extends InputAbstract {
       }
    }
 
-   private String path(String value) throws IOException {
+   private static String path(String value) throws IOException {
       return path(new File(value));
    }
 
-   private String path(File value) throws IOException {
+   private static String path(File value) throws IOException {
       return value.getCanonicalPath();
    }
 
    private void write(String source, HashMap<String, String> filters, boolean unixTarget) throws Exception {
-      write(source, new File(directory, source), filters, unixTarget);
+      write(source, new File(directory, source), filters, unixTarget, force);
    }
 
    private void writeEtc(String source, File etcFolder, HashMap<String, String> filters, boolean unixTarget) throws Exception {
-      write("etc/" + source, new File(etcFolder, source), filters, unixTarget);
-   }
-
-   private void write(String source,
-                      File target,
-                      HashMap<String, String> filters,
-                      boolean unixTarget) throws Exception {
-      if (target.exists() && !force) {
-         throw new CLIException(String.format("The file '%s' already exists.  Use --force to overwrite.", target));
-      }
-
-      String content = readTextFile(source, filters);
-
-      // and then writing out in the new target encoding..  Let's also replace \n with the values
-      // that is correct for the current platform.
-      String separator = unixTarget && IS_CYGWIN ? "\n" : System.getProperty("line.separator");
-      content = content.replaceAll("\\r?\\n", Matcher.quoteReplacement(separator));
-      ByteArrayInputStream in = new ByteArrayInputStream(content.getBytes(encoding));
-      try (FileOutputStream fout = new FileOutputStream(target)) {
-         copy(in, fout);
-      }
-   }
-
-   private String applyFilters(String content, Map<String, String> filters) throws IOException {
-
-      if (filters != null) {
-         for (Map.Entry<String, String> entry : filters.entrySet()) {
-            try {
-               content = replace(content, entry.getKey(), entry.getValue());
-            } catch (Throwable e) {
-               getActionContext().out.println("Error on " + entry.getKey());
-               e.printStackTrace();
-               System.exit(-1);
-            }
-         }
-      }
-      return content;
-   }
-
-   private String readTextFile(String source, Map<String, String> filters) throws IOException {
-      ByteArrayOutputStream out = new ByteArrayOutputStream();
-      try (InputStream in = openStream(source)) {
-         copy(in, out);
-      }
-      return applyFilters(new String(out.toByteArray(), StandardCharsets.UTF_8), filters);
-   }
-
-   private void write(String source) throws IOException {
-      File target = new File(directory, source);
-      if (target.exists() && !force) {
-         throw new RuntimeException(String.format("The file '%s' already exists.  Use --force to overwrite.", target));
-      }
-      try (FileOutputStream fout = new FileOutputStream(target)) {
-         try (InputStream in = openStream(source)) {
-            copy(in, fout);
-         }
-      }
-   }
-
-   private String replace(String content, String key, String value) {
-      return content.replaceAll(Pattern.quote(key), Matcher.quoteReplacement(value));
-   }
-
-   private void copy(InputStream is, OutputStream os) throws IOException {
-      byte[] buffer = new byte[1024 * 4];
-      int c = is.read(buffer);
-      while (c >= 0) {
-         os.write(buffer, 0, c);
-         c = is.read(buffer);
-      }
+      write("etc/" + source, new File(etcFolder, source), filters, unixTarget, force);
    }
 
    private enum SecurityManagerType {
@@ -1240,4 +1128,4 @@ public class Create extends InputAbstract {
          }
       }
    }
-}
+}
\ No newline at end of file
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/InstallAbstract.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/InstallAbstract.java
new file mode 100644
index 0000000000..8b3ed5bd01
--- /dev/null
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/InstallAbstract.java
@@ -0,0 +1,176 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.activemq.artemis.cli.commands;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import io.airlift.airline.Arguments;
+import io.airlift.airline.Option;
+import org.apache.activemq.artemis.cli.CLIException;
+
+public class InstallAbstract extends InputAbstract {
+
+   @Arguments(description = "The instance directory to hold the broker's configuration and data. Path must be writable.", required = true)
+   protected File directory;
+
+   @Option(name = "--etc", description = "Directory where ActiveMQ configuration is located. Paths can be absolute or relative to artemis.instance directory ('etc' by default)")
+   protected String etc = "etc";
+
+   @Option(name = "--home", description = "Directory where ActiveMQ Artemis is installed")
+   protected File home;
+
+   @Option(name = "--encoding", description = "The encoding that text files should use. Default = UTF-8.")
+   protected String encoding = "UTF-8";
+
+   @Option(name = "--windows", description = "Force windows script creation. Default based on your actual system.")
+   protected boolean windows = false;
+
+   @Option(name = "--cygwin", description = "Force cygwin script creation. Default based on your actual system.")
+   protected boolean cygwin = false;
+
+   @Option(name = "--java-options", description = "Extra java options to be passed to the profile")
+   protected String javaOptions = "";
+
+   @Option(name = "--java-memory", description = "Define the -Xmx memory parameter for the broker. Default = '2G'")
+   protected String javaMemory = "2G";
+
+
+   public String getEncoding() {
+      return encoding;
+   }
+
+   public void setEncoding(String encoding) {
+      this.encoding = encoding;
+   }
+
+   public File getInstance() {
+      return directory;
+   }
+
+   public void setInstance(File directory) {
+      this.directory = directory;
+   }
+
+   public File getHome() {
+      if (home == null) {
+         home = new File(getBrokerHome());
+      }
+      return home;
+   }
+
+   protected boolean IS_WINDOWS;
+   protected boolean IS_CYGWIN;
+
+   public Object run(ActionContext context) throws Exception {
+      IS_WINDOWS = windows | System.getProperty("os.name").toLowerCase().trim().startsWith("win");
+      IS_CYGWIN = cygwin | IS_WINDOWS && "cygwin".equals(System.getenv("OSTYPE"));
+
+      return null;
+   }
+
+   protected String applyFilters(String content, Map<String, String> filters) {
+      if (filters != null) {
+         for (Map.Entry<String, String> entry : filters.entrySet()) {
+            content = replace(content, entry.getKey(), entry.getValue());
+         }
+      }
+      return content;
+   }
+
+   protected String replace(String content, String key, String value) {
+      return content.replaceAll(Pattern.quote(key), Matcher.quoteReplacement(value));
+   }
+
+
+   protected void copy(InputStream is, OutputStream os) throws IOException {
+      byte[] buffer = new byte[1024 * 4];
+      int c = is.read(buffer);
+      while (c >= 0) {
+         os.write(buffer, 0, c);
+         c = is.read(buffer);
+      }
+   }
+
+
+   protected void write(String source,
+                      File target,
+                      HashMap<String, String> filters,
+                      boolean unixTarget, boolean force) throws Exception {
+      if (target.exists() && !force) {
+         throw new CLIException(String.format("The file '%s' already exists.  Use --force to overwrite.", target));
+      }
+
+      String content = readTextFile(source, filters);
+
+      if (content == null) {
+         new Exception(source + " not found").printStackTrace();
+      }
+
+      // and then writing out in the new target encoding..  Let's also replace \n with the values
+      // that is correct for the current platform.
+      String separator = unixTarget && IS_CYGWIN ? "\n" : System.getProperty("line.separator");
+      content = content.replaceAll("\\r?\\n", Matcher.quoteReplacement(separator));
+      ByteArrayInputStream in = new ByteArrayInputStream(content.getBytes(encoding));
+      try (FileOutputStream fout = new FileOutputStream(target)) {
+         copy(in, fout);
+      }
+   }
+
+   protected String readTextFile(String source, Map<String, String> filters) throws IOException {
+      ByteArrayOutputStream out = new ByteArrayOutputStream();
+      try (InputStream in = openStream(source)) {
+         if (in == null) {
+            throw new IOException("could not find resource " + source);
+         }
+         copy(in, out);
+      }
+      return applyFilters(new String(out.toByteArray(), StandardCharsets.UTF_8), filters);
+   }
+
+   protected void write(String source, boolean force) throws IOException {
+      File target = new File(directory, source);
+      if (target.exists() && !force) {
+         throw new RuntimeException(String.format("The file '%s' already exists.  Use --force to overwrite.", target));
+      }
+      try (FileOutputStream fout = new FileOutputStream(target)) {
+         try (InputStream in = openStream(source)) {
+            copy(in, fout);
+         }
+      }
+   }
+
+   /**
+    * This method is made public for the testsuite
+    */
+   public InputStream openStream(String source) {
+      return this.getClass().getResourceAsStream(source);
+   }
+
+
+}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Run.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Run.java
index 62dc89e855..6c2f7e50a5 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Run.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Run.java
@@ -75,6 +75,8 @@ public class Run extends LockAbstract {
    public Object execute(ActionContext context) throws Exception {
       super.execute(context);
 
+      verifyOlderLogging(new File(getBrokerEtc()));
+
       AtomicReference<Throwable> serverActivationFailed = new AtomicReference<>();
       try {
          BrokerDTO broker = getBrokerDTO();
@@ -225,4 +227,20 @@ public class Run extends LockAbstract {
          e.printStackTrace();
       }
    }
+
+
+   public static final String OLD_LOG_NAME = "logging.properties";
+
+   public static void verifyOlderLogging(File etc) throws Exception {
+      File newLogging = new File(etc, Create.ETC_LOG4J2_PROPERTIES);
+      File oldLogging = new File(etc, OLD_LOG_NAME);
+
+      if (oldLogging.exists() && !newLogging.exists()) {
+         System.out.println("******************************************************************************************************************************************************************************");
+         System.out.println("Your system has the older logging file " + OLD_LOG_NAME + ", but not the new " + Create.ETC_LOG4J2_PROPERTIES);
+         System.out.println("It appears you did not complete the migration on this artemis instance properly. Please check all the settings or run the './artemis upgrade' command from the new artemis home");
+         System.out.println("******************************************************************************************************************************************************************************");
+      }
+   }
+
 }
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Upgrade.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Upgrade.java
new file mode 100644
index 0000000000..d0e04e9047
--- /dev/null
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Upgrade.java
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.cli.commands;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import io.airlift.airline.Command;
+
+@Command(name = "upgrade", description = "Update an artemis instance to the current artemis.home, keeping all the data and broker.xml. Warning: backup your instance before using this command and compare the files.")
+public class Upgrade extends InstallAbstract {
+   /**
+    * Checks that the directory provided either exists and is writable or doesn't exist but can be created.
+    */
+   protected void checkDirectory() {
+      if (!directory.exists()) {
+         throw new RuntimeException(String.format("Could not find path '%s' to upgrade.", directory));
+      } else if (!directory.canWrite()) {
+         throw new RuntimeException(String.format("The path '%s' is not writable.", directory));
+      }
+   }
+
+
+   @Override
+   public Object execute(ActionContext context) throws Exception {
+      this.checkDirectory();
+      super.execute(context);
+
+      return run(context);
+   }
+
+   @Override
+   public Object run(ActionContext context) throws Exception {
+      super.run(context);
+      context.out.println("*******************************************************************************************************************************");
+      context.out.println("Upgrading broker instance " + directory + " to use artemis.home=" + getBrokerHome());
+
+      File bkpFolder = findBackup(context);
+      File binBkp = new File(bkpFolder, "bin");
+      File etcBkp = new File(bkpFolder, "etc");
+      File tmp = new File(bkpFolder, "tmp");
+      binBkp.mkdirs();
+      etcBkp.mkdirs();
+      tmp.mkdirs();
+
+      File bin = new File(directory, "bin");
+      File etcFolder = new File(directory, etc);
+
+      if (etc == null || etc.equals("etc")) {
+         if (IS_WINDOWS && !IS_CYGWIN) {
+            File cmd = new File(bin, Create.ARTEMIS_CMD);
+            String pattern = "set ARTEMIS_INSTANCE_ETC=";
+            etcFolder = getETC(context, etcFolder, cmd, pattern);
+         } else {
+            File cmd = new File(bin, Create.ARTEMIS);
+            String pattern = "ARTEMIS_INSTANCE_ETC=";
+            etcFolder = getETC(context, etcFolder, cmd, pattern);
+         }
+      }
+
+      if (bin == null || !bin.exists()) { // it can't be null, just being cautious
+         throw new IOException(bin + " does not exist for binary");
+      }
+
+      if (etcFolder == null || !etcFolder.exists()) { // it can't be null, just being cautious
+         throw new IOException(etcFolder + " does not exist for etc");
+      }
+
+      HashMap<String, String> filters = new HashMap<>();
+      Create.addScriptFilters(filters, getHome(), getInstance(), etcFolder, new File(getInstance(), "notUsed"), new File(getInstance(), "om-not-used.dmp"), javaMemory, javaOptions, "NA");
+
+      if (IS_WINDOWS) {
+         write(Create.BIN_ARTEMIS_CMD, new File(tmp, Create.ARTEMIS_CMD), filters, false, false);
+         upgrade(new File(tmp, Create.ARTEMIS_CMD), new File(bin, Create.ARTEMIS_CMD), binBkp, "set ARTEMIS_INSTANCE_ETC=");
+
+         write(Create.BIN_ARTEMIS_SERVICE_XML, new File(tmp, Create.ARTEMIS_SERVICE_XML), filters, false, false);
+         upgrade(new File(tmp, Create.ARTEMIS_SERVICE_XML), new File(bin, Create.ARTEMIS_SERVICE_XML), binBkp,
+                 "<env name=\"ARTEMIS_INSTANCE\"", "<env name=\"ARTEMIS_INSTANCE_ETC\"",
+                 "<env name=\"ARTEMIS_INSTANCE_URI\"", "<env name=\"ARTEMIS_INSTANCE_ETC_URI\"",
+                 "<env name=\"ARTEMIS_DATA_DIR\"", "<logpath>", "<startargument>-Xmx", "<stopargument>-Xmx");
+
+         write("etc/" + Create.ETC_ARTEMIS_PROFILE_CMD, new File(tmp, Create.ETC_ARTEMIS_PROFILE_CMD), filters, false, false);
+         upgrade(new File(tmp, Create.ETC_ARTEMIS_PROFILE_CMD), new File(etcFolder, Create.ETC_ARTEMIS_PROFILE_CMD), binBkp,
+                 "set ARTEMIS_INSTANCE=\"", "set ARTEMIS_DATA_DIR=", "set ARTEMIS_ETC_DIR=", "set ARTEMIS_OOME_DUMP=", "set ARTEMIS_INSTANCE_URI=", "set ARTEMIS_INSTANCE_ETC_URI=");
+      }
+
+      if (!IS_WINDOWS || IS_CYGWIN) {
+         write(Create.BIN_ARTEMIS, new File(tmp, Create.ARTEMIS), filters, false, false);
+         upgrade(new File(tmp, Create.ARTEMIS), new File(bin, Create.ARTEMIS), binBkp, "ARTEMIS_INSTANCE_ETC=");
+
+         write(Create.BIN_ARTEMIS_SERVICE, new File(tmp, Create.ARTEMIS_SERVICE), filters, false, false);
+         upgrade(new File(tmp, Create.ARTEMIS_SERVICE), new File(bin, Create.ARTEMIS_SERVICE), binBkp); // we replace the whole thing
+
+         write("etc/" + Create.ETC_ARTEMIS_PROFILE, new File(tmp, Create.ETC_ARTEMIS_PROFILE), filters, false, false);
+         upgrade(new File(tmp, Create.ETC_ARTEMIS_PROFILE), new File(etcFolder, Create.ETC_ARTEMIS_PROFILE), etcBkp, "ARTEMIS_INSTANCE=",
+                 "ARTEMIS_DATA_DIR=", "ARTEMIS_ETC_DIR=", "ARTEMIS_OOME_DUMP=", "ARTEMIS_INSTANCE_URI=", "ARTEMIS_INSTANCE_ETC_URI=", "HAWTIO_ROLE=");
+      }
+
+      upgradeLogging(context, etcBkp, etcFolder);
+
+      context.out.println();
+      context.out.println("*******************************************************************************************************************************");
+
+      return null;
+   }
+
+   private File getETC(ActionContext context, File etcFolder, File cmd, String pattern) throws IOException {
+      String etcLine = getLine(cmd, pattern);
+      if (etcLine != null) {
+         etcLine = etcLine.trim();
+         etcLine = etcLine.substring(pattern.length() + 1, etcLine.length() - 1);
+         etcFolder = new File(etcLine);
+         context.out.println("ETC found at " + etcFolder);
+      }
+      return etcFolder;
+   }
+
+   private String getLine(File cmd, String pattern) throws IOException {
+      Stream<String> lines = Files.lines(cmd.toPath());
+      Iterator<String> iterator = lines.iterator();
+      while (iterator.hasNext()) {
+         String line = iterator.next();
+         if (line.trim().startsWith(pattern)) {
+            return line;
+         }
+      }
+      return null;
+   }
+
+   private void upgrade(File tmpFile, File targetFile, File bkp, String... keepingPrefixes) throws Exception {
+      HashMap<String, String> replaceMatrix = new HashMap<>();
+
+      doUpgrade(tmpFile, targetFile, bkp,
+              line -> {
+                 for (String prefix : keepingPrefixes) {
+                    if (line.trim().startsWith(prefix)) {
+                       replaceMatrix.put(prefix, line);
+                    }
+                 }
+              }, line -> {
+            for (String prefix : keepingPrefixes) {
+               if (line.trim().startsWith(prefix)) {
+                  String original = replaceMatrix.get(prefix);
+                  return original;
+               }
+            }
+            return line;
+         });
+   }
+
+   private void doUpgrade(File tmpFile, File targetFile, File bkp, Consumer<String> originalConsumer, Function<String, String> targetFunction) throws Exception {
+      Files.copy(targetFile.toPath(), bkp.toPath(), StandardCopyOption.REPLACE_EXISTING);
+
+      // we first scan the original lines on the originalConsumer, giving a chance to the caller to fill out the original matrix
+      Stream<String> originalLines = Files.lines(targetFile.toPath());
+      originalLines.forEach(line -> {
+         if (originalConsumer != null) {
+            originalConsumer.accept(line);
+         }
+      });
+
+      // now we open the new file from the tmp, and we will give a chance for the targetFunction to replace lines from a matrix
+      try (Stream<String> lines = Files.lines(tmpFile.toPath());
+           PrintStream streamOutput = new PrintStream(new FileOutputStream(targetFile))) {
+
+         Iterator<String> linesIterator = lines.iterator();
+         while (linesIterator.hasNext()) {
+            String line = linesIterator.next();
+            line = targetFunction.apply(line);
+            if (line != null) {
+               streamOutput.println(line);
+            }
+         }
+      }
+   }
+
+   private void upgradeLogging(ActionContext context, File bkpFolder, File etc) throws Exception {
+      File oldLogging = new File(etc, "logging.properties");
+
+      if (oldLogging.exists()) {
+         context.out.println("Moving " + oldLogging + " under " + bkpFolder);
+         File oldLoggingCopy = new File(bkpFolder, "logging.properties");
+         context.out.println(oldLogging.toPath() + " copy as " + oldLoggingCopy.toPath());
+         Files.copy(oldLogging.toPath(), bkpFolder.toPath(), StandardCopyOption.REPLACE_EXISTING);
+         oldLogging.delete();
+         File newLogging = new File(etc, Create.ETC_LOG4J2_PROPERTIES);
+
+
+         if (!newLogging.exists()) {
+            context.out.println("Creating " + newLogging);
+            InputStream inputStream = getClass().getResourceAsStream("etc/" + Create.ETC_LOG4J2_PROPERTIES);
+            OutputStream outputStream = new FileOutputStream(newLogging);
+            outputStream.write(inputStream.readAllBytes());
+            inputStream.close();
+         }
+      }
+   }
+
+   protected File findBackup(ActionContext context) {
+      for (int bkp = 0; bkp < 10; bkp++) {
+         File bkpFolder = new File(directory, "old-config-bkp." + bkp);
+         if (!bkpFolder.exists()) {
+            bkpFolder.mkdirs();
+            context.out.println("Using " + bkpFolder.getAbsolutePath() + " as a backup folder for the modified files");
+            return bkpFolder;
+         }
+      }
+      throw new RuntimeException("Too many backup folders in place already. Please remove some of the old-config-bkp.* folders");
+   }
+
+
+}
diff --git a/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/bin/artemis-service.xml b/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/bin/artemis-service.xml
index 0f7881b5e9..fc76661261 100644
--- a/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/bin/artemis-service.xml
+++ b/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/bin/artemis-service.xml
@@ -23,13 +23,13 @@
    <description>Apache ActiveMQ Artemis is a reliable messaging broker</description>
 
    <env name="ARTEMIS_HOME" value="${artemis.home}"/>
-   <env name="ARTEMIS_INSTANCE" value="${artemis.instance}"/>
+   <env name="ARTEMIS_INSTANCE" value="@artemis.instance@"/>
    <env name="ARTEMIS_INSTANCE_ETC" value="${artemis.instance.etc}"/>
    <env name="ARTEMIS_INSTANCE_URI" value="${artemis.instance.uri}"/>
    <env name="ARTEMIS_INSTANCE_ETC_URI" value="${artemis.instance.etc.uri.windows}"/>
    <env name="ARTEMIS_DATA_DIR" value="${artemis.instance.data}"/>
 
-   <logpath>${artemis.instance}\log</logpath>
+   <logpath>@artemis.instance@\log</logpath>
    <logmode>roll</logmode>
 
    <executable>%JAVA_HOME%\bin\java.exe</executable>
diff --git a/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/artemis.profile b/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/artemis.profile
index 56d8adf83e..e0b857fa26 100644
--- a/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/artemis.profile
+++ b/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/artemis.profile
@@ -16,7 +16,7 @@
 # under the License.
 
 ARTEMIS_HOME='${artemis.home}'
-ARTEMIS_INSTANCE='${artemis.instance}'
+ARTEMIS_INSTANCE='@artemis.instance@'
 ARTEMIS_DATA_DIR='${artemis.instance.data}'
 ARTEMIS_ETC_DIR='${artemis.instance.etc}'
 ARTEMIS_OOME_DUMP='${artemis.instance.oome.dump}'
diff --git a/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/artemis.profile.cmd b/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/artemis.profile.cmd
index c4ebbff04a..0d7c1e5acb 100644
--- a/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/artemis.profile.cmd
+++ b/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/artemis.profile.cmd
@@ -17,7 +17,7 @@ rem specific language governing permissions and limitations
 rem under the License.
 
 set ARTEMIS_HOME="${artemis.home}"
-set ARTEMIS_INSTANCE="${artemis.instance}"
+set ARTEMIS_INSTANCE="@artemis.instance@"
 set ARTEMIS_DATA_DIR="${artemis.instance.data}"
 set ARTEMIS_ETC_DIR="${artemis.instance.etc}"
 set ARTEMIS_OOME_DUMP="${artemis.instance.oome.dump}"
diff --git a/artemis-maven-plugin/src/main/java/org/apache/activemq/artemis/maven/ArtemisUpgradePlugin.java b/artemis-maven-plugin/src/main/java/org/apache/activemq/artemis/maven/ArtemisUpgradePlugin.java
new file mode 100644
index 0000000000..1d21fee762
--- /dev/null
+++ b/artemis-maven-plugin/src/main/java/org/apache/activemq/artemis/maven/ArtemisUpgradePlugin.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.maven;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.activemq.artemis.boot.Artemis;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.project.MavenProject;
+
+@Mojo(name = "upgrade", defaultPhase = LifecyclePhase.TEST_COMPILE)
+public class ArtemisUpgradePlugin extends ArtemisAbstractPlugin {
+
+   @Parameter
+   String name;
+
+   /**
+    * The plugin descriptor
+    */
+   private PluginDescriptor descriptor;
+
+   @Parameter(defaultValue = "${activemq.basedir}", required = true)
+   private File home;
+
+   @Parameter(defaultValue = "${activemq.basedir}/artemis-distribution/target/apache-artemis-${project.version}-bin/apache-artemis-${project.version}/", required = true)
+   private File alternateHome;
+
+   @Parameter(defaultValue = "${basedir}/target/server0", required = true)
+   private File instance;
+
+   @Parameter
+   private String[] args;
+
+
+   @Override
+   protected boolean isIgnore() {
+      return false;
+   }
+
+   @Parameter boolean useSystemOutput = getLog().isDebugEnabled();
+
+   private void add(List<String> list, String... str) {
+      for (String s : str) {
+         list.add(s);
+      }
+   }
+
+   @Override
+   protected void doExecute() throws MojoExecutionException, MojoFailureException {
+      getLog().debug("Local " + localRepository);
+      MavenProject project = (MavenProject) getPluginContext().get("project");
+
+      if (!isArtemisHome(home.toPath())) {
+         if (isArtemisHome(alternateHome.toPath())) {
+            home = alternateHome;
+         } else {
+            getLog().error("********************************************************************************************");
+            getLog().error("Could not locate suitable Artemis.home on either " + home + " or " + alternateHome);
+            getLog().error("Use the binary distribution or build the distribution before running the examples");
+            getLog().error("********************************************************************************************");
+
+            throw new MojoExecutionException("Couldn't find artemis.home");
+         }
+      }
+
+      Map properties = getPluginContext();
+
+      Set<Map.Entry> entries = properties.entrySet();
+
+      if (getLog().isDebugEnabled()) {
+         getLog().debug("Entries.size " + entries.size());
+         for (Map.Entry entry : entries) {
+            getLog().debug("... key=" + entry.getKey() + " = " + entry.getValue());
+         }
+      }
+
+      ArrayList<String> listCommands = new ArrayList<>();
+
+      add(listCommands, "upgrade");
+
+      add(listCommands, instance.getAbsolutePath());
+
+      if (args != null) {
+         for (String a : args) {
+            add(listCommands, a);
+         }
+      }
+      getLog().debug("***** Server upgrading at " + instance + " with home=" + home + " *****");
+
+      try {
+         Artemis.execute(home, null, null, useSystemOutput, listCommands);
+      } catch (Throwable e) {
+         getLog().error(e);
+         throw new MojoFailureException(e.getMessage());
+      }
+   }
+}
diff --git a/docs/user-manual/en/upgrading.md b/docs/user-manual/en/upgrading.md
index 4eddda3c76..e82c2eb30f 100644
--- a/docs/user-manual/en/upgrading.md
+++ b/docs/user-manual/en/upgrading.md
@@ -16,18 +16,18 @@ Because of this separation it's very easy to upgrade Artemis in most cases.
 
 > **Note:**
 >
-> It's recommended to choose a folder different than the on where Apache
+> It's recommended to choose a folder different from where Apache
 > Artemis was downloaded. This separation allows you run multiple broker
 > instances with the same Artemis "home" for example. It also simplifies
 > updating to newer versions of Artemis. 
-
+ 
 ## General Upgrade Procedure
 
 Upgrading may require some specific steps noted in the [versions](versions.md),
 but the general process is as follows:
 
 1. Navigate to the `etc` folder of the broker instance that's being upgraded
-1. Open `artemis.profile` (`artemis.profile.cmd` on Windows). It contains a
+2. Open `artemis.profile` (`artemis.profile.cmd` on Windows). It contains a
    property which is relevant for the upgrade:
 
    ```
@@ -37,7 +37,7 @@ but the general process is as follows:
 If you run Artemis as a service on windows you have to do the following additional steps:
 
 1. Navigate to the `bin` folder of the broker instance that's being upgraded
-1. Open `artemis-service.xml`. It contains a property which is relevant for the upgrade:
+2. Open `artemis-service.xml`. It contains a property which is relevant for the upgrade:
 
    ```
    <env name="ARTEMIS_HOME" value="/path/to/apache-artemis-version"/>
@@ -48,3 +48,23 @@ most cases_ the instance can be upgraded to a newer version simply by changing
 the value of this property to the location of the new broker home. Please refer
 to the aforementioned [versions](versions.md) document for additional upgrade
 steps (if required).
+
+It is also possible to do these steps automatically as it can be seen in the next section.
+
+## Upgrading tool
+
+An automatic approach can be used to upgrade the instance. You may simply call `./artemis upgrade <old-instance>`.
+
+```shell
+cd $NEW_ARTEMIS_DOWNLOAD/bin/
+./artemis upgrade PATH_TO_UPGRADING_INSTANCE
+```
+
+artemis, artemis.profile will be updated to the new version.
+
+The tool will also update log4j2.properties (if you are migrating from a version previous to 2.27.0).
+
+> **Note:**
+> 
+>Eventual customizations to your scripts will be lost, however the script will copy the older version at a created old-config-bkp folder.
+
diff --git a/docs/user-manual/en/versions.md b/docs/user-manual/en/versions.md
index 65f134181d..ba94c14714 100644
--- a/docs/user-manual/en/versions.md
+++ b/docs/user-manual/en/versions.md
@@ -9,8 +9,10 @@ This chapter provides the following information for each release:
     chapter in addition to any version-specific upgrade instructions outlined here.
 
 ## 2.27.0
+[Full release notes](https://issues.apache.org/jira/secure/ReleaseNote.jspa?version=12352246&projectId=12315920)
 
 Highlights:
+- 2.27.0 Introduced a new upgrade tool to help migrating your instance to a newer version. Simply use `./artemis upgrade <path-to-your-instance>` from the new downloaded broker.
 - The client and broker now use [SLF4J](https://www.slf4j.org/) for their logging API.
 - The broker distribution now uses [Log4J 2](https://logging.apache.org/log4j/2.x/manual/) as its logging implementation.
 
diff --git a/tests/smoke-tests/pom.xml b/tests/smoke-tests/pom.xml
index a2951950a6..1607bc60c7 100644
--- a/tests/smoke-tests/pom.xml
+++ b/tests/smoke-tests/pom.xml
@@ -191,6 +191,22 @@
    </dependencies>
 
    <build>
+      <resources>
+         <resource>
+            <directory>src/main/resources</directory>
+            <filtering>false</filtering>
+            <includes>
+               <include>**/*</include>
+            </includes>
+         </resource>
+         <resource>
+            <directory>src/main/filtered-resources</directory>
+            <filtering>true</filtering>
+            <includes>
+               <include>**/*</include>
+            </includes>
+         </resource>
+      </resources>
       <plugins>
          <plugin>
             <artifactId>maven-resources-plugin</artifactId>
@@ -1212,6 +1228,29 @@
                      </args>
                   </configuration>
                </execution>
+               <execution>
+                  <phase>test-compile</phase>
+                  <id>upgrade</id>
+                  <goals>
+                     <goal>upgrade</goal>
+                  </goals>
+                  <configuration>
+                     <instance>${basedir}/target/classes/servers/toUpgradeTest</instance>
+                  </configuration>
+               </execution>
+               <execution>
+                  <phase>test-compile</phase>
+                  <id>upgrade-windows</id>
+                  <goals>
+                     <goal>upgrade</goal>
+                  </goals>
+                  <configuration>
+                     <instance>${basedir}/target/classes/servers/windows</instance>
+                     <args>
+                        <arg>--windows</arg>
+                     </args>
+                  </configuration>
+               </execution>
             </executions>
             <dependencies>
                <dependency>
diff --git a/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/artemis-roles.properties b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/artemis-roles.properties
new file mode 100644
index 0000000000..ee6feea790
--- /dev/null
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/artemis-roles.properties
@@ -0,0 +1,18 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+amq = y
\ No newline at end of file
diff --git a/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/artemis-users.properties b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/artemis-users.properties
new file mode 100644
index 0000000000..47025bdaab
--- /dev/null
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/artemis-users.properties
@@ -0,0 +1,18 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+y = ENC(1024:4D83B7E5E85B4F43D65E31E9C7A69055D13BB165E54F57078F3E5D3DA188F3ED:3D71F9F4D6396B43255D37B47E859357DC244759B9BF5BCCA19DAD8C613E1A7302EF7A433BE2463B6AC4057B7227271C23659BF50CFE30ACE49F891C63F2A7D2)
\ No newline at end of file
diff --git a/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/artemis.profile b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/artemis.profile
similarity index 72%
copy from artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/artemis.profile
copy to tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/artemis.profile
index 56d8adf83e..4f0539bae0 100644
--- a/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/artemis.profile
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/artemis.profile
@@ -15,17 +15,17 @@
 # specific language governing permissions and limitations
 # under the License.
 
-ARTEMIS_HOME='${artemis.home}'
-ARTEMIS_INSTANCE='${artemis.instance}'
-ARTEMIS_DATA_DIR='${artemis.instance.data}'
-ARTEMIS_ETC_DIR='${artemis.instance.etc}'
-ARTEMIS_OOME_DUMP='${artemis.instance.oome.dump}'
+ARTEMIS_HOME='must-change'
+ARTEMIS_INSTANCE='${project.basedir}/target/classes/servers/toUpgradeTest'
+ARTEMIS_DATA_DIR='${project.basedir}/target/classes/servers/toUpgradeTest/data'
+ARTEMIS_ETC_DIR='${project.basedir}/target/classes/servers/toUpgradeETC'
+ARTEMIS_OOME_DUMP='${project.basedir}/target/classes/servers/toUpgradeTest/log/oom_dump.hprof'
 
 # The logging config will need an URI
 # this will be encoded in case you use spaces or special characters
 # on your directory structure
-ARTEMIS_INSTANCE_URI='${artemis.instance.uri}'
-ARTEMIS_INSTANCE_ETC_URI='${artemis.instance.etc.uri}'
+ARTEMIS_INSTANCE_URI='file:${project.basedir}/target/classes/servers/toUpgradeTest'
+ARTEMIS_INSTANCE_ETC_URI='file:${project.basedir}/target/classes/servers/toUpgradeETC'
 
 # Cluster Properties: Used to pass arguments to ActiveMQ Artemis which can be referenced in broker.xml
 #ARTEMIS_CLUSTER_PROPS="-Dactivemq.remoting.default.port=61617 -Dactivemq.remoting.amqp.port=5673 -Dactivemq.remoting.stomp.port=61614 -Dactivemq.remoting.hornetq.port=5446"
@@ -33,11 +33,13 @@ ARTEMIS_INSTANCE_ETC_URI='${artemis.instance.etc.uri}'
 # Hawtio Properties
 # HAWTIO_ROLE define the user role or roles required to be able to login to the console. Multiple roles to allow can
 # be separated by a comma. Set to '*' or an empty value to disable role checking when Hawtio authenticates a user.
-HAWTIO_ROLE='${role}'
+HAWTIO_ROLE='amq'
 
 # Java Opts
 if [ -z "$JAVA_ARGS" ]; then
-    JAVA_ARGS="-XX:AutoBoxCacheMax=20000 -XX:+PrintClassHistogram -XX:+UseG1GC -XX:+UseStringDeduplication -Xms512M -Xmx${java-memory} -Dhawtio.disableProxy=true -Dhawtio.realm=activemq -Dhawtio.offline=true -Dhawtio.rolePrincipalClasses=org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal -Djolokia.policyLocation=${ARTEMIS_INSTANCE_ETC_URI}jolokia-access.xml ${java-opts}"
+    #### I am adding a customization to the JAVA-ARGS that would be replaced
+    #### If this line is seen on the upgrade it means that things are not working
+    JAVA_ARGS="-should-not-work -XX:+PrintClassHistogram -XX:+UseG1GC -XX:+UseStringDeduplication -Xms512M -Xmx2G -Dhawtio.disableProxy=true -Dhawtio.realm=activemq -Dhawtio.offline=true -Dhawtio.rolePrincipalClasses=org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal -Djolokia.policyLocation=${ARTEMIS_INSTANCE_ETC_URI}jolokia-access.xml "
 fi
 
 # Uncomment to enable logging for Safepoint JVM pauses
diff --git a/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/bootstrap.xml b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/bootstrap.xml
new file mode 100644
index 0000000000..c16bcf9082
--- /dev/null
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/bootstrap.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  ~ 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.
+  -->
+
+<broker xmlns="http://activemq.apache.org/schema">
+
+   <jaas-security domain="activemq"/>
+
+
+   <!-- artemis.URI.instance is parsed from artemis.instance by the CLI startup.
+        This is to avoid situations where you could have spaces or special characters on this URI -->
+   <server configuration="file:${project.basedir}/target/classes/servers/toUpgradeETC/broker.xml"/>
+
+   <!-- The web server is only bound to localhost by default -->
+   <web path="web">
+       <binding uri="http://localhost:8161">
+           <app url="activemq-branding" war="activemq-branding.war"/>
+           <app url="artemis-plugin" war="artemis-plugin.war"/>
+           <app url="console" war="console.war"/>
+       </binding>
+   </web>
+
+
+</broker>
+
diff --git a/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/broker.xml b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/broker.xml
new file mode 100644
index 0000000000..c88da8e62f
--- /dev/null
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/broker.xml
@@ -0,0 +1,254 @@
+<?xml version='1.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.
+-->
+
+<configuration xmlns="urn:activemq"
+               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+               xmlns:xi="http://www.w3.org/2001/XInclude"
+               xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd">
+
+   <core xmlns="urn:activemq:core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="urn:activemq:core ">
+
+      <name>0.0.0.0</name>
+
+
+      <persistence-enabled>true</persistence-enabled>
+
+      <!-- this could be ASYNCIO, MAPPED, NIO
+           ASYNCIO: Linux Libaio
+           MAPPED: mmap files
+           NIO: Plain Java Files
+       -->
+      <journal-type>NIO</journal-type>
+
+      <paging-directory>data/paging</paging-directory>
+
+      <bindings-directory>data/bindings</bindings-directory>
+
+      <journal-directory>data/journal</journal-directory>
+
+      <large-messages-directory>data/large-messages</large-messages-directory>
+
+      
+      <!-- if you want to retain your journal uncomment this following configuration.
+
+      This will allow your system to keep 7 days of your data, up to 10G. Tweak it accordingly to your use case and capacity.
+
+      it is recommended to use a separate storage unit from the journal for performance considerations.
+
+      <journal-retention-directory period="7" unit="DAYS" storage-limit="10G">data/retention</journal-retention-directory>
+
+      You can also enable retention by using the argument journal-retention on the `artemis create` command -->
+
+
+
+      <journal-datasync>true</journal-datasync>
+
+      <journal-min-files>2</journal-min-files>
+
+      <journal-pool-files>10</journal-pool-files>
+
+      <journal-device-block-size>4096</journal-device-block-size>
+
+      <journal-file-size>10M</journal-file-size>
+            <!--
+        You can verify the network health of a particular NIC by specifying the <network-check-NIC> element.
+         <network-check-NIC>theNicName</network-check-NIC>
+        -->
+
+      <!--
+        Use this to use an HTTP server to validate the network
+         <network-check-URL-list>http://www.apache.org</network-check-URL-list> -->
+
+      <!-- <network-check-period>10000</network-check-period> -->
+      <!-- <network-check-timeout>1000</network-check-timeout> -->
+
+      <!-- this is a comma separated list, no spaces, just DNS or IPs
+           it should accept IPV6
+
+           Warning: Make sure you understand your network topology as this is meant to validate if your network is valid.
+                    Using IPs that could eventually disappear or be partially visible may defeat the purpose.
+                    You can use a list of multiple IPs, and if any successful ping will make the server OK to continue running -->
+      <!-- <network-check-list>10.0.0.1</network-check-list> -->
+
+      <!-- use this to customize the ping used for ipv4 addresses -->
+      <!-- <network-check-ping-command>ping -c 1 -t %d %s</network-check-ping-command> -->
+
+      <!-- use this to customize the ping used for ipv6 addresses -->
+      <!-- <network-check-ping6-command>ping6 -c 1 %2$s</network-check-ping6-command> -->
+
+
+
+
+      <!-- how often we are looking for how many bytes are being used on the disk in ms -->
+      <disk-scan-period>5000</disk-scan-period>
+
+      <!-- once the disk hits this limit the system will block, or close the connection in certain protocols
+           that won't support flow control. -->
+      <max-disk-usage>90</max-disk-usage>
+
+      <!-- should the broker detect dead locks and other issues -->
+      <critical-analyzer>true</critical-analyzer>
+
+      <critical-analyzer-timeout>120000</critical-analyzer-timeout>
+
+      <critical-analyzer-check-period>60000</critical-analyzer-check-period>
+
+      <critical-analyzer-policy>HALT</critical-analyzer-policy>
+
+      
+
+      <!-- the system will enter into page mode once you hit this limit. This is an estimate in bytes of how much the messages are using in memory
+
+      The system will use half of the available memory (-Xmx) by default for the global-max-size.
+      You may specify a different value here if you need to customize it to your needs.
+
+      <global-max-size>100Mb</global-max-size> -->
+
+      <!-- the maximum number of messages accepted before entering full address mode.
+           if global-max-size is specified the full address mode will be specified by whatever hits it first. -->
+      <global-max-messages>-1</global-max-messages>
+
+      <acceptors>
+
+         <!-- useEpoll means: it will use Netty epoll if you are on a system (Linux) that supports it -->
+         <!-- amqpCredits: The number of credits sent to AMQP producers -->
+         <!-- amqpLowCredits: The server will send the # credits specified at amqpCredits at this low mark -->
+         <!-- amqpDuplicateDetection: If you are not using duplicate detection, set this to false
+                                      as duplicate detection requires applicationProperties to be parsed on the server. -->
+         <!-- amqpMinLargeMessageSize: Determines how many bytes are considered large, so we start using files to hold their data.
+                                       default: 102400, -1 would mean to disable large mesasge control -->
+
+         <!-- Note: If an acceptor needs to be compatible with HornetQ and/or Artemis 1.x clients add
+                    "anycastPrefix=jms.queue.;multicastPrefix=jms.topic." to the acceptor url.
+                    See https://issues.apache.org/jira/browse/ARTEMIS-1644 for more information. -->
+
+
+         <!-- Acceptor for every supported protocol -->
+         <acceptor name="artemis">tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;amqpMinLargeMessageSize=102400;protocols=CORE,AMQP,STOMP,HORNETQ,MQTT,OPENWIRE;useEpoll=true;amqpCredits=1000;amqpLowCredits=300;amqpDuplicateDetection=true;supportAdvisory=false;suppressInternalManagementObjects=false</acceptor>
+
+         <!-- AMQP Acceptor.  Listens on default AMQP port for AMQP traffic.-->
+         <acceptor name="amqp">tcp://0.0.0.0:5672?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=AMQP;useEpoll=true;amqpCredits=1000;amqpLowCredits=300;amqpMinLargeMessageSize=102400;amqpDuplicateDetection=true</acceptor>
+
+         <!-- STOMP Acceptor. -->
+         <acceptor name="stomp">tcp://0.0.0.0:61613?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=STOMP;useEpoll=true</acceptor>
+
+         <!-- HornetQ Compatibility Acceptor.  Enables HornetQ Core and STOMP for legacy HornetQ clients. -->
+         <acceptor name="hornetq">tcp://0.0.0.0:5445?anycastPrefix=jms.queue.;multicastPrefix=jms.topic.;protocols=HORNETQ,STOMP;useEpoll=true</acceptor>
+
+         <!-- MQTT Acceptor -->
+         <acceptor name="mqtt">tcp://0.0.0.0:1883?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=MQTT;useEpoll=true</acceptor>
+
+      </acceptors>
+
+
+      <security-settings>
+         <security-setting match="#">
+            <permission type="createNonDurableQueue" roles="amq"/>
+            <permission type="deleteNonDurableQueue" roles="amq"/>
+            <permission type="createDurableQueue" roles="amq"/>
+            <permission type="deleteDurableQueue" roles="amq"/>
+            <permission type="createAddress" roles="amq"/>
+            <permission type="deleteAddress" roles="amq"/>
+            <permission type="consume" roles="amq"/>
+            <permission type="browse" roles="amq"/>
+            <permission type="send" roles="amq"/>
+            <!-- we need this otherwise ./artemis data imp wouldn't work -->
+            <permission type="manage" roles="amq"/>
+         </security-setting>
+      </security-settings>
+
+      <address-settings>
+         <!-- if you define auto-create on certain queues, management has to be auto-create -->
+         <address-setting match="activemq.management#">
+            <dead-letter-address>DLQ</dead-letter-address>
+            <expiry-address>ExpiryQueue</expiry-address>
+            <redelivery-delay>0</redelivery-delay>
+            <!-- with -1 only the global-max-size is in use for limiting -->
+            <max-size-bytes>-1</max-size-bytes>
+            <message-counter-history-day-limit>10</message-counter-history-day-limit>
+            <address-full-policy>PAGE</address-full-policy>
+            <auto-create-queues>true</auto-create-queues>
+            <auto-create-addresses>true</auto-create-addresses>
+         </address-setting>
+         <!--default for catch all-->
+         <address-setting match="#">
+            <dead-letter-address>DLQ</dead-letter-address>
+            <expiry-address>ExpiryQueue</expiry-address>
+            <redelivery-delay>0</redelivery-delay>
+
+            <!-- if max-size-bytes and max-size-messages were both enabled, the system will enter into paging
+                 based on the first attribute to hits the maximum value -->
+            <!-- limit for the address in bytes, -1 means unlimited -->
+            <max-size-bytes>-1</max-size-bytes>
+
+            <!-- limit for the address in messages, -1 means unlimited -->
+            <max-size-messages>-1</max-size-messages>
+
+            <!-- the size of each file on paging. Notice we keep files in memory while they are in use.
+                 Lower this setting if you have too many queues in memory. -->
+            <page-size-bytes>10M</page-size-bytes>
+
+            <!-- limit how many messages are read from paging into the Queue. -->
+            <max-read-page-messages>-1</max-read-page-messages>
+
+            <!-- limit how much memory is read from paging into the Queue. -->
+            <max-read-page-bytes>20M</max-read-page-bytes>
+
+            <message-counter-history-day-limit>10</message-counter-history-day-limit>
+            <address-full-policy>PAGE</address-full-policy>
+            <auto-create-queues>true</auto-create-queues>
+            <auto-create-addresses>true</auto-create-addresses>
+            <auto-delete-queues>false</auto-delete-queues>
+            <auto-delete-addresses>false</auto-delete-addresses>
+         </address-setting>
+      </address-settings>
+
+      <addresses>
+         <address name="DLQ">
+            <anycast>
+               <queue name="DLQ" />
+            </anycast>
+         </address>
+         <address name="ExpiryQueue">
+            <anycast>
+               <queue name="ExpiryQueue" />
+            </anycast>
+         </address>
+
+      </addresses>
+
+
+      <!-- Uncomment the following if you want to use the Standard LoggingActiveMQServerPlugin pluging to log in events
+      <broker-plugins>
+         <broker-plugin class-name="org.apache.activemq.artemis.core.server.plugin.impl.LoggingActiveMQServerPlugin">
+            <property key="LOG_ALL_EVENTS" value="true"/>
+            <property key="LOG_CONNECTION_EVENTS" value="true"/>
+            <property key="LOG_SESSION_EVENTS" value="true"/>
+            <property key="LOG_CONSUMER_EVENTS" value="true"/>
+            <property key="LOG_DELIVERING_EVENTS" value="true"/>
+            <property key="LOG_SENDING_EVENTS" value="true"/>
+            <property key="LOG_INTERNAL_EVENTS" value="true"/>
+         </broker-plugin>
+      </broker-plugins>
+      -->
+
+   </core>
+</configuration>
diff --git a/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/jolokia-access.xml b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/jolokia-access.xml
new file mode 100644
index 0000000000..679523f896
--- /dev/null
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/jolokia-access.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+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.
+-->
+
+<!-- This policy file controls the Jolokia JMX-HTTP bridge security options for the web console.
+   see: https://jolokia.org/reference/html/security.html -->
+<restrict>
+
+    <cors>
+        <!-- Allow cross origin access from localhost ... -->
+        <allow-origin>*://localhost*</allow-origin>
+
+
+        <!-- Options from this point on are auto-generated by Create.java from the Artemis CLI -->
+        <!-- Check for the proper origin on the server side, too -->
+        <strict-checking/>
+    </cors>
+
+</restrict>
\ No newline at end of file
diff --git a/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/logging.properties b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/logging.properties
new file mode 100644
index 0000000000..97980b99c2
--- /dev/null
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/logging.properties
@@ -0,0 +1,90 @@
+#
+# 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.
+#
+
+# Additional logger names to configure (root logger is always configured)
+# Root logger option
+loggers=org.eclipse.jetty,org.jboss.logging,org.apache.activemq.artemis.core.server,org.apache.activemq.artemis.utils,org.apache.activemq.artemis.utils.critical,org.apache.activemq.artemis.journal,org.apache.activemq.artemis.jms.server,org.apache.activemq.artemis.integration.bootstrap,org.apache.activemq.audit.base,org.apache.activemq.audit.message,org.apache.activemq.audit.resource,org.apache.curator,org.apache.zookeeper
+
+# Root logger level
+logger.level=INFO
+# ActiveMQ Artemis logger levels
+logger.org.apache.activemq.artemis.core.server.level=INFO
+logger.org.apache.activemq.artemis.journal.level=INFO
+logger.org.apache.activemq.artemis.utils.level=INFO
+
+# if you have issues with CriticalAnalyzer, setting this as TRACE would give you extra troubleshooting information.
+# but do not use it regularly as it would incur in some extra CPU usage for this diagnostic.
+logger.org.apache.activemq.artemis.utils.critical.level=INFO
+
+logger.org.apache.activemq.artemis.jms.level=INFO
+logger.org.apache.activemq.artemis.integration.bootstrap.level=INFO
+logger.org.eclipse.jetty.level=WARN
+# Root logger handlers
+logger.handlers=FILE,CONSOLE
+
+# quorum logger levels
+logger.org.apache.curator.level=WARN
+logger.org.apache.zookeeper.level=ERROR
+
+# to enable audit change the level to INFO
+logger.org.apache.activemq.audit.base.level=ERROR
+logger.org.apache.activemq.audit.base.handlers=AUDIT_FILE
+logger.org.apache.activemq.audit.base.useParentHandlers=false
+
+logger.org.apache.activemq.audit.resource.level=ERROR
+logger.org.apache.activemq.audit.resource.handlers=AUDIT_FILE
+logger.org.apache.activemq.audit.resource.useParentHandlers=false
+
+logger.org.apache.activemq.audit.message.level=ERROR
+logger.org.apache.activemq.audit.message.handlers=AUDIT_FILE
+logger.org.apache.activemq.audit.message.useParentHandlers=false
+
+# Console handler configuration
+handler.CONSOLE=org.jboss.logmanager.handlers.ConsoleHandler
+handler.CONSOLE.properties=autoFlush
+handler.CONSOLE.level=DEBUG
+handler.CONSOLE.autoFlush=true
+handler.CONSOLE.formatter=PATTERN
+
+# File handler configuration
+handler.FILE=org.jboss.logmanager.handlers.PeriodicRotatingFileHandler
+handler.FILE.level=DEBUG
+handler.FILE.properties=suffix,append,autoFlush,fileName
+handler.FILE.suffix=.yyyy-MM-dd
+handler.FILE.append=true
+handler.FILE.autoFlush=true
+handler.FILE.fileName=${artemis.instance}/log/artemis.log
+handler.FILE.formatter=PATTERN
+
+# Formatter pattern configuration
+formatter.PATTERN=org.jboss.logmanager.formatters.PatternFormatter
+formatter.PATTERN.properties=pattern
+formatter.PATTERN.pattern=%d %-5p [%c] %s%E%n
+
+#Audit logger
+handler.AUDIT_FILE=org.jboss.logmanager.handlers.PeriodicRotatingFileHandler
+handler.AUDIT_FILE.level=INFO
+handler.AUDIT_FILE.properties=suffix,append,autoFlush,fileName
+handler.AUDIT_FILE.suffix=.yyyy-MM-dd
+handler.AUDIT_FILE.append=true
+handler.AUDIT_FILE.autoFlush=true
+handler.AUDIT_FILE.fileName=${artemis.instance}/log/audit.log
+handler.AUDIT_FILE.formatter=AUDIT_PATTERN
+
+formatter.AUDIT_PATTERN=org.jboss.logmanager.formatters.PatternFormatter
+formatter.AUDIT_PATTERN.properties=pattern
+formatter.AUDIT_PATTERN.pattern=%d [AUDIT](%t) %s%E%n
diff --git a/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/login.config b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/login.config
new file mode 100644
index 0000000000..bcdf92893f
--- /dev/null
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/login.config
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+activemq {
+   org.apache.activemq.artemis.spi.core.security.jaas.PropertiesLoginModule sufficient
+       debug=false
+       reload=true
+       org.apache.activemq.jaas.properties.user="artemis-users.properties"
+       org.apache.activemq.jaas.properties.role="artemis-roles.properties";
+
+   org.apache.activemq.artemis.spi.core.security.jaas.GuestLoginModule sufficient
+       debug=false
+       org.apache.activemq.jaas.guest.user="y"
+       org.apache.activemq.jaas.guest.role="amq";
+};
\ No newline at end of file
diff --git a/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/management.xml b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/management.xml
new file mode 100644
index 0000000000..002ee95050
--- /dev/null
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeETC/management.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  ~ 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.
+  -->
+<management-context xmlns="http://activemq.apache.org/schema">
+   <!--<connector connector-port="1099"/>-->
+   <authorisation>
+      <allowlist>
+         <entry domain="hawtio"/>
+      </allowlist>
+      <default-access>
+         <access method="list*" roles="amq"/>
+         <access method="get*" roles="amq"/>
+         <access method="is*" roles="amq"/>
+         <access method="set*" roles="amq"/>
+         <access method="*" roles="amq"/>
+      </default-access>
+      <role-access>
+         <match domain="org.apache.activemq.artemis">
+            <access method="list*" roles="amq"/>
+            <access method="get*" roles="amq"/>
+            <access method="is*" roles="amq"/>
+            <access method="set*" roles="amq"/>
+            <!-- Note count and browse are need to access the browse tab in the console-->
+            <access method="browse*" roles="amq"/>
+            <access method="count*" roles="amq"/>
+            <access method="*" roles="amq"/>
+         </match>
+         <!--example of how to configure a specific object-->
+         <!--<match domain="org.apache.activemq.artemis" key="subcomponent=queues">
+            <access method="list*" roles="view,update,amq"/>
+            <access method="get*" roles="view,update,amq"/>
+            <access method="is*" roles="view,update,amq"/>
+            <access method="set*" roles="update,amq"/>
+            <access method="*" roles="amq"/>
+         </match>-->
+      </role-access>
+   </authorisation>
+</management-context>
\ No newline at end of file
diff --git a/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeTest/bin/artemis b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeTest/bin/artemis
new file mode 100755
index 0000000000..ebb92a0f78
--- /dev/null
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeTest/bin/artemis
@@ -0,0 +1,24 @@
+#!/usr/bin/env sh
+# 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.
+
+
+## I removed everything from this file, except to the line that matters.
+## the upgrade should keep this line in the new script
+
+
+ARTEMIS_INSTANCE_ETC='${project.basedir}/target/classes/servers/toUpgradeETC'
diff --git a/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeTest/bin/artemis-service b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeTest/bin/artemis-service
new file mode 100755
index 0000000000..491f881a29
--- /dev/null
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/toUpgradeTest/bin/artemis-service
@@ -0,0 +1,158 @@
+#!/usr/bin/env sh
+# 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.
+
+service=`basename "$0"`
+
+#
+# Discover the ARTEMIS_INSTANCE from the location of this script.
+#
+if [ -z "$ARTEMIS_INSTANCE" ] ; then
+
+  ## resolve links - $0 may be a link to ActiveMQ's home
+  PRG="$0"
+  saveddir=`pwd`
+
+  # need this for relative symlinks
+  dirname_prg=`dirname "$PRG"`
+  cd "$dirname_prg"
+
+  while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '.*/.*' > /dev/null; then
+      PRG="$link"
+    else
+      PRG=`dirname "$PRG"`"/$link"
+    fi
+  done
+
+  ARTEMIS_INSTANCE=`dirname "$PRG"`
+  cd "$saveddir"
+
+  # make it fully qualified
+  ARTEMIS_INSTANCE=`cd "$ARTEMIS_INSTANCE/.." && pwd`
+  export ARTEMIS_INSTANCE
+
+fi
+
+PID_FILE="${ARTEMIS_INSTANCE}/data/artemis.pid"
+
+if [ ! -d "${ARTEMIS_INSTANCE}/data/" ]; then
+    mkdir "${ARTEMIS_INSTANCE}/data/"
+fi
+
+status() {
+  if [ -f "${PID_FILE}" ] ; then
+    pid=`cat "${PID_FILE}"`
+    # check to see if it's gone...
+    ps -p ${pid} > /dev/null
+    if [ $? -eq 0 ] ; then
+      return 0
+    else
+      rm "${PID_FILE}"
+      return 3
+    fi
+  fi
+  return 3
+}
+
+stop() {
+  if [ -f "${PID_FILE}" ] ; then
+    pid=`cat "${PID_FILE}"`
+    kill $@ ${pid} > /dev/null
+  fi
+  for i in 1 2 3 4 5 ; do
+    status
+    if [ $? -ne 0 ] ; then
+      return 0
+    fi
+    sleep 1
+  done
+  echo "Could not stop process ${pid}"
+  return 1
+}
+
+start() {
+
+  status
+  if [ $? -eq 0 ] ; then
+    echo "Already running."
+    return 1
+  fi
+
+  if [ -z "$ARTEMIS_USER" -o `id -un` = "$ARTEMIS_USER" ] ; then
+    nohup "${ARTEMIS_INSTANCE}/bin/artemis" run > /dev/null 2> /dev/null &
+  else
+    sudo -n -u ${ARTEMIS_USER} nohup "${ARTEMIS_INSTANCE}/bin/artemis" run > /dev/null 2> /dev/null &
+  fi
+
+  echo $! > "${PID_FILE}"
+
+  # check to see if stays up...
+  sleep 1
+  status
+  if [ $? -ne 0 ] ; then
+    echo "Could not start ${service}"
+    return 1
+  fi
+  echo "${service} is now running (${pid})"
+  return 0
+}
+
+case $1 in
+  start)
+    echo "Starting ${service}"
+    start
+    exit $?
+  ;;
+
+  force-stop)
+    echo "Forcibly Stopping ${service}"
+    stop -9
+    exit $?
+  ;;
+
+  stop)
+    echo "Gracefully Stopping ${service}"
+    stop
+    exit $?
+  ;;
+
+  restart)
+    echo "Restarting ${service}"
+    stop
+    start
+    exit $?
+  ;;
+
+  status)
+    status
+    rc=$?
+    if [ $rc -eq 0 ] ; then
+      echo "${service} is running (${pid})"
+    else
+      echo "${service} is stopped"
+    fi
+    exit $rc
+  ;;
+
+  *)
+    echo "Usage: $0 {start|stop|restart|force-stop|status}" >&2
+    exit 2
+  ;;
+esac
diff --git a/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/bin/artemis-service.xml b/tests/smoke-tests/src/main/filtered-resources/servers/windows/bin/artemis-service.xml
similarity index 84%
copy from artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/bin/artemis-service.xml
copy to tests/smoke-tests/src/main/filtered-resources/servers/windows/bin/artemis-service.xml
index 0f7881b5e9..e31e8db1e6 100644
--- a/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/bin/artemis-service.xml
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/windows/bin/artemis-service.xml
@@ -18,18 +18,18 @@
 -->
 
 <service>
-   <id>artemis-${artemis.instance.name}-${host}</id>
-   <name>ActiveMQ Artemis: ${artemis.instance.name} @ ${host}</name>
+   <id>artemis-windows-0.0.0.0</id>
+   <name>ActiveMQ Artemis: windows @ 0.0.0.0</name>
    <description>Apache ActiveMQ Artemis is a reliable messaging broker</description>
 
-   <env name="ARTEMIS_HOME" value="${artemis.home}"/>
-   <env name="ARTEMIS_INSTANCE" value="${artemis.instance}"/>
-   <env name="ARTEMIS_INSTANCE_ETC" value="${artemis.instance.etc}"/>
-   <env name="ARTEMIS_INSTANCE_URI" value="${artemis.instance.uri}"/>
-   <env name="ARTEMIS_INSTANCE_ETC_URI" value="${artemis.instance.etc.uri.windows}"/>
-   <env name="ARTEMIS_DATA_DIR" value="${artemis.instance.data}"/>
+   <env name="ARTEMIS_HOME" value="must-change"/>
+   <env name="ARTEMIS_INSTANCE" value="no-change"/>
+   <env name="ARTEMIS_INSTANCE_ETC" value="${project.basedir}/target/classes/servers/windowsETC"/>
+   <env name="ARTEMIS_INSTANCE_URI" value="file:/no-change"/>
+   <env name="ARTEMIS_INSTANCE_ETC_URI" value="file:${project.basedir}/target/classes/servers/windowsETC"/>
+   <env name="ARTEMIS_DATA_DIR" value="no-change"/>
 
-   <logpath>${artemis.instance}\log</logpath>
+   <logpath>/must-be/servers/windows\log</logpath>
    <logmode>roll</logmode>
 
    <executable>%JAVA_HOME%\bin\java.exe</executable>
@@ -54,7 +54,7 @@
    <startargument>-Dhawtio.disableProxy=true</startargument>
    <startargument>-Dhawtio.realm=activemq</startargument>
    <startargument>-Dhawtio.offline="true"</startargument>
-   <startargument>-Dhawtio.role=${role}</startargument>
+   <startargument>-Dhawtio.role=amq</startargument>
    <startargument>-Dhawtio.rolePrincipalClasses=org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal</startargument>
    <startargument>-Djolokia.policyLocation=%ARTEMIS_INSTANCE_ETC_URI%/jolokia-access.xml</startargument>
 
diff --git a/tests/smoke-tests/src/main/filtered-resources/servers/windows/bin/artemis.cmd b/tests/smoke-tests/src/main/filtered-resources/servers/windows/bin/artemis.cmd
new file mode 100644
index 0000000000..299675660a
--- /dev/null
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/windows/bin/artemis.cmd
@@ -0,0 +1,76 @@
+@echo off
+rem Licensed to the Apache Software Foundation (ASF) under one
+rem or more contributor license agreements.  See the NOTICE file
+rem distributed with this work for additional information
+rem regarding copyright ownership.  The ASF licenses this file
+rem to you under the Apache License, Version 2.0 (the
+rem "License"); you may not use this file except in compliance
+rem with the License.  You may obtain a copy of the License at
+rem
+rem   http://www.apache.org/licenses/LICENSE-2.0
+rem
+rem Unless required by applicable law or agreed to in writing,
+rem software distributed under the License is distributed on an
+rem "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+rem KIND, either express or implied.  See the License for the
+rem specific language governing permissions and limitations
+rem under the License.
+
+setlocal
+
+if NOT "%ARTEMIS_INSTANCE%"=="" goto CHECK_ARTEMIS_INSTANCE
+set ARTEMIS_INSTANCE="%~dp0.."
+
+:CHECK_ARTEMIS_INSTANCE
+if exist %ARTEMIS_INSTANCE%\bin\artemis.cmd goto CHECK_JAVA
+
+:NO_HOME
+echo ARTEMIS_INSTANCE environment variable is set incorrectly. Please set ARTEMIS_INSTANCE.
+goto END
+
+:CHECK_JAVA
+set _JAVACMD=%JAVACMD%
+
+if "%JAVA_HOME%" == "" goto NO_JAVA_HOME
+if not exist "%JAVA_HOME%\bin\java.exe" goto NO_JAVA_HOME
+if "%_JAVACMD%" == "" set _JAVACMD=%JAVA_HOME%\bin\java.exe
+goto RUN_JAVA
+
+:NO_JAVA_HOME
+if "%_JAVACMD%" == "" set _JAVACMD=java.exe
+echo.
+echo Warning: JAVA_HOME environment variable is not set.
+echo.
+
+:RUN_JAVA
+
+rem "Load Profile Config"
+set ARTEMIS_INSTANCE_ETC="${project.basedir}/target/classes/servers/windowsETC"
+call %ARTEMIS_INSTANCE_ETC%\artemis.profile.cmd %*
+
+if not exist %ARTEMIS_OOME_DUMP% goto NO_ARTEMIS_OOME_DUMP
+rem "Backup the last OOME heap dump"
+move /Y %ARTEMIS_OOME_DUMP% %ARTEMIS_OOME_DUMP%.bkp
+
+:NO_ARTEMIS_OOME_DUMP
+
+rem "Create full JVM Args"
+set JVM_ARGS=%JAVA_ARGS%
+if not "%ARTEMIS_CLUSTER_PROPS%"=="" set JVM_ARGS=%JVM_ARGS% %ARTEMIS_CLUSTER_PROPS%
+set JVM_ARGS=%JVM_ARGS% -classpath %ARTEMIS_HOME%\lib\artemis-boot.jar
+set JVM_ARGS=%JVM_ARGS% -Dartemis.home=%ARTEMIS_HOME%
+set JVM_ARGS=%JVM_ARGS% -Dartemis.instance=%ARTEMIS_INSTANCE%
+set JVM_ARGS=%JVM_ARGS% -Ddata.dir=%ARTEMIS_DATA_DIR%
+set JVM_ARGS=%JVM_ARGS% -Dartemis.instance.etc=%ARTEMIS_INSTANCE_ETC%
+set JVM_ARGS=%JVM_ARGS% -Dartemis.default.sensitive.string.codec.key=%ARTEMIS_DEFAULT_SENSITIVE_STRING_CODEC_KEY%
+
+if not "%DEBUG_ARGS%"=="" set JVM_ARGS=%JVM_ARGS% %DEBUG_ARGS%
+if not "%$JAVA_ARGS_APPEND%"=="" set JVM_ARGS=%JVM_ARGS% %$JAVA_ARGS_APPEND%
+
+"%_JAVACMD%" %JVM_ARGS% org.apache.activemq.artemis.boot.Artemis %*
+
+:END
+endlocal
+GOTO :EOF
+
+:EOF
diff --git a/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/artemis-roles.properties b/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/artemis-roles.properties
new file mode 100644
index 0000000000..ee6feea790
--- /dev/null
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/artemis-roles.properties
@@ -0,0 +1,18 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+amq = y
\ No newline at end of file
diff --git a/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/artemis-users.properties b/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/artemis-users.properties
new file mode 100644
index 0000000000..8d4122dc45
--- /dev/null
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/artemis-users.properties
@@ -0,0 +1,18 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+y = ENC(1024:F2B5A875934D0DA88F3E7416FA616418DB802AB1B0F8925B2C2A93BDC0AD57B4:A9A5D72B87731DA5CB02F8317028B526032240EC26C371B8DEF771CF0BC4805FB10DD5A9BBAEE9F984300EDB03C4A5018D7A4FE3680A98B4CCF57E79C347EF43)
\ No newline at end of file
diff --git a/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/artemis.profile.cmd b/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/artemis.profile.cmd
similarity index 71%
copy from artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/artemis.profile.cmd
copy to tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/artemis.profile.cmd
index c4ebbff04a..0ea79ca86c 100644
--- a/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/artemis.profile.cmd
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/artemis.profile.cmd
@@ -16,24 +16,24 @@ rem KIND, either express or implied.  See the License for the
 rem specific language governing permissions and limitations
 rem under the License.
 
-set ARTEMIS_HOME="${artemis.home}"
-set ARTEMIS_INSTANCE="${artemis.instance}"
-set ARTEMIS_DATA_DIR="${artemis.instance.data}"
-set ARTEMIS_ETC_DIR="${artemis.instance.etc}"
-set ARTEMIS_OOME_DUMP="${artemis.instance.oome.dump}"
+set ARTEMIS_HOME="must-change"
+set ARTEMIS_INSTANCE="no-change"
+set ARTEMIS_DATA_DIR="no-change"
+set ARTEMIS_ETC_DIR="no-change"
+set ARTEMIS_OOME_DUMP="no-change"
 
 
 rem The logging config will need an URI
 rem this will be encoded in case you use spaces or special characters
 rem on your directory structure
-set ARTEMIS_INSTANCE_URI="${artemis.instance.uri.windows}"
-set ARTEMIS_INSTANCE_ETC_URI="${artemis.instance.etc.uri.windows}"
+set ARTEMIS_INSTANCE_URI="file:/no-change/"
+set ARTEMIS_INSTANCE_ETC_URI="file:/no-change/"
 
 rem Cluster Properties: Used to pass arguments to ActiveMQ Artemis which can be referenced in broker.xml
 rem set ARTEMIS_CLUSTER_PROPS=-Dactivemq.remoting.default.port=61617 -Dactivemq.remoting.amqp.port=5673 -Dactivemq.remoting.stomp.port=61614 -Dactivemq.remoting.hornetq.port=5446
 
 rem Java Opts
-IF "%JAVA_ARGS%"=="" (set JAVA_ARGS=${java-opts} -XX:AutoBoxCacheMax=20000 -XX:+PrintClassHistogram  -XX:+UseG1GC -XX:+UseStringDeduplication -Xms512M -Xmx${java-memory} -Djava.security.auth.login.config=%ARTEMIS_ETC_DIR%\login.config -Dhawtio.disableProxy=true -Dhawtio.offline=true -Dhawtio.realm=activemq -Dhawtio.role=${role} -Dhawtio.rolePrincipalClasses=org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal -Djolokia.policyLocation=%ARTEMIS_INSTANCE_ETC_URI%\jolokia-access. [...]
+IF "%JAVA_ARGS%"=="" (set JAVA_ARGS= -XX:AutoBoxCacheMax=20000 -XX:+PrintClassHistogram  -XX:+UseG1GC -XX:+UseStringDeduplication -Xms512M -Xmx2G -Djava.security.auth.login.config=%ARTEMIS_ETC_DIR%\login.config -Dhawtio.disableProxy=true -Dhawtio.offline=true -Dhawtio.realm=activemq -Dhawtio.role=amq -Dhawtio.rolePrincipalClasses=org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal -Djolokia.policyLocation=%ARTEMIS_INSTANCE_ETC_URI%\jolokia-access.xml -Dartemis.instance=%ARTE [...]
 
 rem Logs Safepoints JVM pauses: Uncomment to enable them
 rem In addition to the traditional GC logs you could enable some JVM flags to know any meaningful and "hidden" pause that could
diff --git a/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/bootstrap.xml b/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/bootstrap.xml
new file mode 100644
index 0000000000..9576de7c55
--- /dev/null
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/bootstrap.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  ~ 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.
+  -->
+
+<broker xmlns="http://activemq.apache.org/schema">
+
+   <jaas-security domain="activemq"/>
+
+
+   <!-- artemis.URI.instance is parsed from artemis.instance by the CLI startup.
+        This is to avoid situations where you could have spaces or special characters on this URI -->
+   <server configuration="file:/no-change/broker.xml"/>
+
+   <!-- The web server is only bound to localhost by default -->
+   <web path="web" rootRedirectLocation="console">
+       <binding uri="http://localhost:8161">
+           <app url="activemq-branding" war="activemq-branding.war"/>
+           <app url="artemis-plugin" war="artemis-plugin.war"/>
+           <app url="console" war="console.war"/>
+       </binding>
+   </web>
+
+
+</broker>
+
diff --git a/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/broker.xml b/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/broker.xml
new file mode 100644
index 0000000000..c88da8e62f
--- /dev/null
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/broker.xml
@@ -0,0 +1,254 @@
+<?xml version='1.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.
+-->
+
+<configuration xmlns="urn:activemq"
+               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+               xmlns:xi="http://www.w3.org/2001/XInclude"
+               xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd">
+
+   <core xmlns="urn:activemq:core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="urn:activemq:core ">
+
+      <name>0.0.0.0</name>
+
+
+      <persistence-enabled>true</persistence-enabled>
+
+      <!-- this could be ASYNCIO, MAPPED, NIO
+           ASYNCIO: Linux Libaio
+           MAPPED: mmap files
+           NIO: Plain Java Files
+       -->
+      <journal-type>NIO</journal-type>
+
+      <paging-directory>data/paging</paging-directory>
+
+      <bindings-directory>data/bindings</bindings-directory>
+
+      <journal-directory>data/journal</journal-directory>
+
+      <large-messages-directory>data/large-messages</large-messages-directory>
+
+      
+      <!-- if you want to retain your journal uncomment this following configuration.
+
+      This will allow your system to keep 7 days of your data, up to 10G. Tweak it accordingly to your use case and capacity.
+
+      it is recommended to use a separate storage unit from the journal for performance considerations.
+
+      <journal-retention-directory period="7" unit="DAYS" storage-limit="10G">data/retention</journal-retention-directory>
+
+      You can also enable retention by using the argument journal-retention on the `artemis create` command -->
+
+
+
+      <journal-datasync>true</journal-datasync>
+
+      <journal-min-files>2</journal-min-files>
+
+      <journal-pool-files>10</journal-pool-files>
+
+      <journal-device-block-size>4096</journal-device-block-size>
+
+      <journal-file-size>10M</journal-file-size>
+            <!--
+        You can verify the network health of a particular NIC by specifying the <network-check-NIC> element.
+         <network-check-NIC>theNicName</network-check-NIC>
+        -->
+
+      <!--
+        Use this to use an HTTP server to validate the network
+         <network-check-URL-list>http://www.apache.org</network-check-URL-list> -->
+
+      <!-- <network-check-period>10000</network-check-period> -->
+      <!-- <network-check-timeout>1000</network-check-timeout> -->
+
+      <!-- this is a comma separated list, no spaces, just DNS or IPs
+           it should accept IPV6
+
+           Warning: Make sure you understand your network topology as this is meant to validate if your network is valid.
+                    Using IPs that could eventually disappear or be partially visible may defeat the purpose.
+                    You can use a list of multiple IPs, and if any successful ping will make the server OK to continue running -->
+      <!-- <network-check-list>10.0.0.1</network-check-list> -->
+
+      <!-- use this to customize the ping used for ipv4 addresses -->
+      <!-- <network-check-ping-command>ping -c 1 -t %d %s</network-check-ping-command> -->
+
+      <!-- use this to customize the ping used for ipv6 addresses -->
+      <!-- <network-check-ping6-command>ping6 -c 1 %2$s</network-check-ping6-command> -->
+
+
+
+
+      <!-- how often we are looking for how many bytes are being used on the disk in ms -->
+      <disk-scan-period>5000</disk-scan-period>
+
+      <!-- once the disk hits this limit the system will block, or close the connection in certain protocols
+           that won't support flow control. -->
+      <max-disk-usage>90</max-disk-usage>
+
+      <!-- should the broker detect dead locks and other issues -->
+      <critical-analyzer>true</critical-analyzer>
+
+      <critical-analyzer-timeout>120000</critical-analyzer-timeout>
+
+      <critical-analyzer-check-period>60000</critical-analyzer-check-period>
+
+      <critical-analyzer-policy>HALT</critical-analyzer-policy>
+
+      
+
+      <!-- the system will enter into page mode once you hit this limit. This is an estimate in bytes of how much the messages are using in memory
+
+      The system will use half of the available memory (-Xmx) by default for the global-max-size.
+      You may specify a different value here if you need to customize it to your needs.
+
+      <global-max-size>100Mb</global-max-size> -->
+
+      <!-- the maximum number of messages accepted before entering full address mode.
+           if global-max-size is specified the full address mode will be specified by whatever hits it first. -->
+      <global-max-messages>-1</global-max-messages>
+
+      <acceptors>
+
+         <!-- useEpoll means: it will use Netty epoll if you are on a system (Linux) that supports it -->
+         <!-- amqpCredits: The number of credits sent to AMQP producers -->
+         <!-- amqpLowCredits: The server will send the # credits specified at amqpCredits at this low mark -->
+         <!-- amqpDuplicateDetection: If you are not using duplicate detection, set this to false
+                                      as duplicate detection requires applicationProperties to be parsed on the server. -->
+         <!-- amqpMinLargeMessageSize: Determines how many bytes are considered large, so we start using files to hold their data.
+                                       default: 102400, -1 would mean to disable large mesasge control -->
+
+         <!-- Note: If an acceptor needs to be compatible with HornetQ and/or Artemis 1.x clients add
+                    "anycastPrefix=jms.queue.;multicastPrefix=jms.topic." to the acceptor url.
+                    See https://issues.apache.org/jira/browse/ARTEMIS-1644 for more information. -->
+
+
+         <!-- Acceptor for every supported protocol -->
+         <acceptor name="artemis">tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;amqpMinLargeMessageSize=102400;protocols=CORE,AMQP,STOMP,HORNETQ,MQTT,OPENWIRE;useEpoll=true;amqpCredits=1000;amqpLowCredits=300;amqpDuplicateDetection=true;supportAdvisory=false;suppressInternalManagementObjects=false</acceptor>
+
+         <!-- AMQP Acceptor.  Listens on default AMQP port for AMQP traffic.-->
+         <acceptor name="amqp">tcp://0.0.0.0:5672?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=AMQP;useEpoll=true;amqpCredits=1000;amqpLowCredits=300;amqpMinLargeMessageSize=102400;amqpDuplicateDetection=true</acceptor>
+
+         <!-- STOMP Acceptor. -->
+         <acceptor name="stomp">tcp://0.0.0.0:61613?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=STOMP;useEpoll=true</acceptor>
+
+         <!-- HornetQ Compatibility Acceptor.  Enables HornetQ Core and STOMP for legacy HornetQ clients. -->
+         <acceptor name="hornetq">tcp://0.0.0.0:5445?anycastPrefix=jms.queue.;multicastPrefix=jms.topic.;protocols=HORNETQ,STOMP;useEpoll=true</acceptor>
+
+         <!-- MQTT Acceptor -->
+         <acceptor name="mqtt">tcp://0.0.0.0:1883?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=MQTT;useEpoll=true</acceptor>
+
+      </acceptors>
+
+
+      <security-settings>
+         <security-setting match="#">
+            <permission type="createNonDurableQueue" roles="amq"/>
+            <permission type="deleteNonDurableQueue" roles="amq"/>
+            <permission type="createDurableQueue" roles="amq"/>
+            <permission type="deleteDurableQueue" roles="amq"/>
+            <permission type="createAddress" roles="amq"/>
+            <permission type="deleteAddress" roles="amq"/>
+            <permission type="consume" roles="amq"/>
+            <permission type="browse" roles="amq"/>
+            <permission type="send" roles="amq"/>
+            <!-- we need this otherwise ./artemis data imp wouldn't work -->
+            <permission type="manage" roles="amq"/>
+         </security-setting>
+      </security-settings>
+
+      <address-settings>
+         <!-- if you define auto-create on certain queues, management has to be auto-create -->
+         <address-setting match="activemq.management#">
+            <dead-letter-address>DLQ</dead-letter-address>
+            <expiry-address>ExpiryQueue</expiry-address>
+            <redelivery-delay>0</redelivery-delay>
+            <!-- with -1 only the global-max-size is in use for limiting -->
+            <max-size-bytes>-1</max-size-bytes>
+            <message-counter-history-day-limit>10</message-counter-history-day-limit>
+            <address-full-policy>PAGE</address-full-policy>
+            <auto-create-queues>true</auto-create-queues>
+            <auto-create-addresses>true</auto-create-addresses>
+         </address-setting>
+         <!--default for catch all-->
+         <address-setting match="#">
+            <dead-letter-address>DLQ</dead-letter-address>
+            <expiry-address>ExpiryQueue</expiry-address>
+            <redelivery-delay>0</redelivery-delay>
+
+            <!-- if max-size-bytes and max-size-messages were both enabled, the system will enter into paging
+                 based on the first attribute to hits the maximum value -->
+            <!-- limit for the address in bytes, -1 means unlimited -->
+            <max-size-bytes>-1</max-size-bytes>
+
+            <!-- limit for the address in messages, -1 means unlimited -->
+            <max-size-messages>-1</max-size-messages>
+
+            <!-- the size of each file on paging. Notice we keep files in memory while they are in use.
+                 Lower this setting if you have too many queues in memory. -->
+            <page-size-bytes>10M</page-size-bytes>
+
+            <!-- limit how many messages are read from paging into the Queue. -->
+            <max-read-page-messages>-1</max-read-page-messages>
+
+            <!-- limit how much memory is read from paging into the Queue. -->
+            <max-read-page-bytes>20M</max-read-page-bytes>
+
+            <message-counter-history-day-limit>10</message-counter-history-day-limit>
+            <address-full-policy>PAGE</address-full-policy>
+            <auto-create-queues>true</auto-create-queues>
+            <auto-create-addresses>true</auto-create-addresses>
+            <auto-delete-queues>false</auto-delete-queues>
+            <auto-delete-addresses>false</auto-delete-addresses>
+         </address-setting>
+      </address-settings>
+
+      <addresses>
+         <address name="DLQ">
+            <anycast>
+               <queue name="DLQ" />
+            </anycast>
+         </address>
+         <address name="ExpiryQueue">
+            <anycast>
+               <queue name="ExpiryQueue" />
+            </anycast>
+         </address>
+
+      </addresses>
+
+
+      <!-- Uncomment the following if you want to use the Standard LoggingActiveMQServerPlugin pluging to log in events
+      <broker-plugins>
+         <broker-plugin class-name="org.apache.activemq.artemis.core.server.plugin.impl.LoggingActiveMQServerPlugin">
+            <property key="LOG_ALL_EVENTS" value="true"/>
+            <property key="LOG_CONNECTION_EVENTS" value="true"/>
+            <property key="LOG_SESSION_EVENTS" value="true"/>
+            <property key="LOG_CONSUMER_EVENTS" value="true"/>
+            <property key="LOG_DELIVERING_EVENTS" value="true"/>
+            <property key="LOG_SENDING_EVENTS" value="true"/>
+            <property key="LOG_INTERNAL_EVENTS" value="true"/>
+         </broker-plugin>
+      </broker-plugins>
+      -->
+
+   </core>
+</configuration>
diff --git a/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/jolokia-access.xml b/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/jolokia-access.xml
new file mode 100644
index 0000000000..679523f896
--- /dev/null
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/jolokia-access.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+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.
+-->
+
+<!-- This policy file controls the Jolokia JMX-HTTP bridge security options for the web console.
+   see: https://jolokia.org/reference/html/security.html -->
+<restrict>
+
+    <cors>
+        <!-- Allow cross origin access from localhost ... -->
+        <allow-origin>*://localhost*</allow-origin>
+
+
+        <!-- Options from this point on are auto-generated by Create.java from the Artemis CLI -->
+        <!-- Check for the proper origin on the server side, too -->
+        <strict-checking/>
+    </cors>
+
+</restrict>
\ No newline at end of file
diff --git a/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/logging.properties b/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/logging.properties
new file mode 100644
index 0000000000..97980b99c2
--- /dev/null
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/logging.properties
@@ -0,0 +1,90 @@
+#
+# 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.
+#
+
+# Additional logger names to configure (root logger is always configured)
+# Root logger option
+loggers=org.eclipse.jetty,org.jboss.logging,org.apache.activemq.artemis.core.server,org.apache.activemq.artemis.utils,org.apache.activemq.artemis.utils.critical,org.apache.activemq.artemis.journal,org.apache.activemq.artemis.jms.server,org.apache.activemq.artemis.integration.bootstrap,org.apache.activemq.audit.base,org.apache.activemq.audit.message,org.apache.activemq.audit.resource,org.apache.curator,org.apache.zookeeper
+
+# Root logger level
+logger.level=INFO
+# ActiveMQ Artemis logger levels
+logger.org.apache.activemq.artemis.core.server.level=INFO
+logger.org.apache.activemq.artemis.journal.level=INFO
+logger.org.apache.activemq.artemis.utils.level=INFO
+
+# if you have issues with CriticalAnalyzer, setting this as TRACE would give you extra troubleshooting information.
+# but do not use it regularly as it would incur in some extra CPU usage for this diagnostic.
+logger.org.apache.activemq.artemis.utils.critical.level=INFO
+
+logger.org.apache.activemq.artemis.jms.level=INFO
+logger.org.apache.activemq.artemis.integration.bootstrap.level=INFO
+logger.org.eclipse.jetty.level=WARN
+# Root logger handlers
+logger.handlers=FILE,CONSOLE
+
+# quorum logger levels
+logger.org.apache.curator.level=WARN
+logger.org.apache.zookeeper.level=ERROR
+
+# to enable audit change the level to INFO
+logger.org.apache.activemq.audit.base.level=ERROR
+logger.org.apache.activemq.audit.base.handlers=AUDIT_FILE
+logger.org.apache.activemq.audit.base.useParentHandlers=false
+
+logger.org.apache.activemq.audit.resource.level=ERROR
+logger.org.apache.activemq.audit.resource.handlers=AUDIT_FILE
+logger.org.apache.activemq.audit.resource.useParentHandlers=false
+
+logger.org.apache.activemq.audit.message.level=ERROR
+logger.org.apache.activemq.audit.message.handlers=AUDIT_FILE
+logger.org.apache.activemq.audit.message.useParentHandlers=false
+
+# Console handler configuration
+handler.CONSOLE=org.jboss.logmanager.handlers.ConsoleHandler
+handler.CONSOLE.properties=autoFlush
+handler.CONSOLE.level=DEBUG
+handler.CONSOLE.autoFlush=true
+handler.CONSOLE.formatter=PATTERN
+
+# File handler configuration
+handler.FILE=org.jboss.logmanager.handlers.PeriodicRotatingFileHandler
+handler.FILE.level=DEBUG
+handler.FILE.properties=suffix,append,autoFlush,fileName
+handler.FILE.suffix=.yyyy-MM-dd
+handler.FILE.append=true
+handler.FILE.autoFlush=true
+handler.FILE.fileName=${artemis.instance}/log/artemis.log
+handler.FILE.formatter=PATTERN
+
+# Formatter pattern configuration
+formatter.PATTERN=org.jboss.logmanager.formatters.PatternFormatter
+formatter.PATTERN.properties=pattern
+formatter.PATTERN.pattern=%d %-5p [%c] %s%E%n
+
+#Audit logger
+handler.AUDIT_FILE=org.jboss.logmanager.handlers.PeriodicRotatingFileHandler
+handler.AUDIT_FILE.level=INFO
+handler.AUDIT_FILE.properties=suffix,append,autoFlush,fileName
+handler.AUDIT_FILE.suffix=.yyyy-MM-dd
+handler.AUDIT_FILE.append=true
+handler.AUDIT_FILE.autoFlush=true
+handler.AUDIT_FILE.fileName=${artemis.instance}/log/audit.log
+handler.AUDIT_FILE.formatter=AUDIT_PATTERN
+
+formatter.AUDIT_PATTERN=org.jboss.logmanager.formatters.PatternFormatter
+formatter.AUDIT_PATTERN.properties=pattern
+formatter.AUDIT_PATTERN.pattern=%d [AUDIT](%t) %s%E%n
diff --git a/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/login.config b/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/login.config
new file mode 100644
index 0000000000..bcdf92893f
--- /dev/null
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/login.config
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+activemq {
+   org.apache.activemq.artemis.spi.core.security.jaas.PropertiesLoginModule sufficient
+       debug=false
+       reload=true
+       org.apache.activemq.jaas.properties.user="artemis-users.properties"
+       org.apache.activemq.jaas.properties.role="artemis-roles.properties";
+
+   org.apache.activemq.artemis.spi.core.security.jaas.GuestLoginModule sufficient
+       debug=false
+       org.apache.activemq.jaas.guest.user="y"
+       org.apache.activemq.jaas.guest.role="amq";
+};
\ No newline at end of file
diff --git a/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/management.xml b/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/management.xml
new file mode 100644
index 0000000000..002ee95050
--- /dev/null
+++ b/tests/smoke-tests/src/main/filtered-resources/servers/windowsETC/management.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  ~ 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.
+  -->
+<management-context xmlns="http://activemq.apache.org/schema">
+   <!--<connector connector-port="1099"/>-->
+   <authorisation>
+      <allowlist>
+         <entry domain="hawtio"/>
+      </allowlist>
+      <default-access>
+         <access method="list*" roles="amq"/>
+         <access method="get*" roles="amq"/>
+         <access method="is*" roles="amq"/>
+         <access method="set*" roles="amq"/>
+         <access method="*" roles="amq"/>
+      </default-access>
+      <role-access>
+         <match domain="org.apache.activemq.artemis">
+            <access method="list*" roles="amq"/>
+            <access method="get*" roles="amq"/>
+            <access method="is*" roles="amq"/>
+            <access method="set*" roles="amq"/>
+            <!-- Note count and browse are need to access the browse tab in the console-->
+            <access method="browse*" roles="amq"/>
+            <access method="count*" roles="amq"/>
+            <access method="*" roles="amq"/>
+         </match>
+         <!--example of how to configure a specific object-->
+         <!--<match domain="org.apache.activemq.artemis" key="subcomponent=queues">
+            <access method="list*" roles="view,update,amq"/>
+            <access method="get*" roles="view,update,amq"/>
+            <access method="is*" roles="view,update,amq"/>
+            <access method="set*" roles="update,amq"/>
+            <access method="*" roles="amq"/>
+         </match>-->
+      </role-access>
+   </authorisation>
+</management-context>
\ No newline at end of file
diff --git a/tests/smoke-tests/src/test/java/org/apache/activemq/artemis/tests/smoke/upgradeTest/CompareUpgradeTest.java b/tests/smoke-tests/src/test/java/org/apache/activemq/artemis/tests/smoke/upgradeTest/CompareUpgradeTest.java
new file mode 100644
index 0000000000..80d00dbd44
--- /dev/null
+++ b/tests/smoke-tests/src/test/java/org/apache/activemq/artemis/tests/smoke/upgradeTest/CompareUpgradeTest.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.activemq.artemis.tests.smoke.upgradeTest;
+
+import java.io.File;
+import java.lang.invoke.MethodHandles;
+import java.nio.file.Files;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** This test will compare expected values at the upgraded servers. */
+public class CompareUpgradeTest {
+
+   private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+   public static final String basedir = System.getProperty("basedir");
+
+   @Test
+   public void testWindows() throws Exception {
+      String windowsBin = basedir + "/target/classes/servers/windows/bin";
+      String windowsETC = basedir + "/target/classes/servers/windowsETC";
+
+      checkExpectedValues(windowsBin + "/artemis.cmd", "set ARTEMIS_INSTANCE_ETC=", "\"" + windowsETC + "\"");
+      Map<String, String> result = checkExpectedValues(windowsBin + "/artemis-service.xml",
+                                                       "<env name=\"ARTEMIS_HOME\" value=", null, // no expected value for this, we will check on the output
+                                                       "<env name=\"ARTEMIS_INSTANCE\" value=", "\"no-change\"/>",
+                                                       "<env name=\"ARTEMIS_INSTANCE_ETC\" value=", "\"" + windowsETC + "\"/>",
+                                                       "<env name=\"ARTEMIS_INSTANCE_URI\" value=", "\"file:/no-change\"/>",
+                                                       "<env name=\"ARTEMIS_DATA_DIR\" value=", "\"no-change\"/>"
+      );
+
+      String home = result.get("<env name=\"ARTEMIS_HOME\" value=");
+      Assert.assertNotNull(home);
+      Assert.assertFalse("home value must be changed during upgrade", home.contains("must-change"));
+
+      result = checkExpectedValues(windowsETC + "/artemis.profile.cmd",
+                                   "set ARTEMIS_HOME=", null, // no expected value for this, we will check on the output
+                                   "set ARTEMIS_INSTANCE=", "\"no-change\"",
+                                   "set ARTEMIS_DATA_DIR=", "\"no-change\"",
+                                   "set ARTEMIS_ETC_DIR=", "\"no-change\"",
+                                   "set ARTEMIS_OOME_DUMP=", "\"no-change\"",
+                                   "set ARTEMIS_INSTANCE_URI=", "\"file:/no-change/\"",
+                                   "set ARTEMIS_INSTANCE_ETC_URI=", "\"file:/no-change/\"");
+
+      home = result.get("set ARTEMIS_HOME=");
+      Assert.assertNotNull(home);
+      Assert.assertFalse("home value must be changed during upgrade", home.contains("must-change"));
+
+      checkExpectedValues(windowsETC + "/bootstrap.xml",
+                          "<server configuration=", "\"file:/no-change/broker.xml\"/>");
+
+      File oldLogging = new File(windowsETC + "/logging.properties");
+      File newLogging = new File(windowsETC + "/log4j2.properties");
+
+      Assert.assertFalse("Old logging must be removed by upgrade", oldLogging.exists());
+      Assert.assertTrue("New Logging must be installed by upgrade", newLogging.exists());
+   }
+
+
+   @Test
+   public void testLinux() throws Exception {
+
+      String instanceDir = basedir + "/target/classes/servers/toUpgradeTest";
+      String bin = instanceDir + "/bin";
+      String etc = basedir + "/target/classes/servers/toUpgradeETC";
+
+      checkExpectedValues(bin + "/artemis", "ARTEMIS_INSTANCE_ETC=", "'" + etc + "'");
+
+      Map<String, String> result = checkExpectedValues(etc + "/artemis.profile",
+                                                       "ARTEMIS_HOME=", null, // no expected value, will check on result
+                                                       "ARTEMIS_INSTANCE=", "'" + instanceDir + "'",
+                                                       "ARTEMIS_DATA_DIR=", "'" + instanceDir + "/data'",
+                                                       "ARTEMIS_ETC_DIR=", "'" + etc + "'",
+                                                       "ARTEMIS_OOME_DUMP=", "'" + instanceDir + "/log/oom_dump.hprof'",
+                                                       "ARTEMIS_INSTANCE_URI=", "'file:" + instanceDir + "'",
+                                                       "ARTEMIS_INSTANCE_ETC_URI=", "'file:" + etc + "'");
+
+      String home = result.get("ARTEMIS_HOME=");
+      Assert.assertNotNull(home);
+      Assert.assertNotEquals("'must-change'", home);
+
+      File oldLogging = new File(etc + "/logging.properties");
+      File newLogging = new File(etc + "/log4j2.properties");
+
+      Assert.assertFalse("Old logging must be removed by upgrade", oldLogging.exists());
+      Assert.assertTrue("New Logging must be installed by upgrade", newLogging.exists());
+   }
+
+
+   private Map<String, String> checkExpectedValues(String fileName, String... expectedPairs) throws Exception {
+      Assert.assertTrue("You must pass a pair of expected values", expectedPairs.length > 0 && expectedPairs.length % 2 == 0);
+      HashMap<String, String> expectedValues = new HashMap<>();
+      HashMap<String, String> matchingValues = new HashMap<>();
+
+      for (int i = 0; i < expectedPairs.length; i += 2) {
+         Assert.assertFalse("Value duplicated on pairs ::" + expectedPairs[i], expectedValues.containsKey(expectedPairs[i]));
+         expectedValues.put(expectedPairs[i], expectedPairs[i + 1]);
+      }
+
+      File file = new File(fileName);
+      Stream<String> lines = Files.lines(file.toPath());
+      lines.forEach(line -> {
+         String trimmedLine = line.trim();
+         expectedValues.forEach((key, value) -> {
+            if (trimmedLine.startsWith(key)) {
+               String actualValue = trimmedLine.substring(key.length());
+               logger.debug("match = {}", line);
+               matchingValues.put(key, actualValue);
+
+               if (value == null) {
+                  logger.debug("no expected value was defined for {}, we will just fill out the matchingValues for further evaluation", key);
+               } else {
+                  logger.debug("prefix={}, expecting={}, actualValue={}", key, value, actualValue);
+                  Assert.assertEquals(key + " did not match", value, actualValue);
+               }
+            }
+         });
+      });
+
+      Assert.assertEquals("Some elements were not found in the output of " + fileName, matchingValues.size(), expectedValues.size());
+
+      return matchingValues;
+   }
+}
diff --git a/tests/smoke-tests/src/test/java/org/apache/activemq/artemis/tests/smoke/upgradeTest/UpgradeTest.java b/tests/smoke-tests/src/test/java/org/apache/activemq/artemis/tests/smoke/upgradeTest/UpgradeTest.java
new file mode 100644
index 0000000000..75501318ef
--- /dev/null
+++ b/tests/smoke-tests/src/test/java/org/apache/activemq/artemis/tests/smoke/upgradeTest/UpgradeTest.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
+ * <br>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <br>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.activemq.artemis.tests.smoke.upgradeTest;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+import java.io.File;
+
+import org.apache.activemq.artemis.tests.smoke.common.SmokeTestBase;
+import org.apache.activemq.artemis.tests.util.CFUtil;
+import org.apache.activemq.artemis.util.ServerUtil;
+import org.apache.activemq.artemis.utils.RandomUtil;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/** This test is making sure the upgrade command would be able to upgrade a test I created with artemis 2.25.0 */
+public class UpgradeTest extends SmokeTestBase {
+
+   File upgradedServer;
+
+   Process processServer;
+
+   @Before
+   public void beforeTest() throws Exception {
+      upgradedServer = new File(basedir + "/target/classes/servers/toUpgradeTest");
+      deleteDirectory(new File(upgradedServer, "data"));
+      deleteDirectory(new File(upgradedServer, "log"));
+
+      processServer = ServerUtil.startServer(upgradedServer.getAbsolutePath(), "upgradedServer", 0, 5000);
+      addProcess(processServer);
+   }
+
+   @Test
+   public void testSimpleSendReceive() throws Throwable {
+
+      ConnectionFactory factory = CFUtil.createConnectionFactory("core", "tcp://localhost:61616");
+
+      try (Connection connection = factory.createConnection()) {
+         connection.start();
+         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         MessageConsumer consumer = session.createConsumer(session.createQueue(getName()));
+         MessageProducer producer = session.createProducer(session.createQueue(getName()));
+         String randomString = "Hello " + RandomUtil.randomString();
+         producer.send(session.createTextMessage(randomString));
+         TextMessage message = (TextMessage)consumer.receive(5000);
+         Assert.assertNotNull(message);
+         Assert.assertEquals(randomString, message.getText());
+      }
+
+   }
+
+}