Yair Zaslavsky has uploaded a new change for review.

Change subject: aaa: Extensions tester tool
......................................................................

aaa: Extensions tester tool

Change-Id: I7ea2f9c62ced5bdd3801c9f6d8087a35e3c21886
Topic: AAA
Signed-off-by: Yair Zaslavsky <yzasl...@redhat.com>
---
A backend/manager/extension-tool/pom.xml
A 
backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsTool.java
A 
backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsToolArguments.java
A 
backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsToolExecutor.java
A backend/manager/extension-tool/src/main/modules/module.xml
A 
backend/manager/extension-tool/src/main/modules/org/ovirt/engine/core/extension-tool/main/module.xml
A 
backend/manager/extension-tool/src/main/resources/extensions-tool/help.properties
A backend/manager/extension-tool/src/main/resources/extensions-tool/jaas.conf
A backend/manager/extension-tool/src/main/resources/extensions-tool/log4j.xml
M 
backend/manager/modules/extensions-manager/src/main/java/org/ovirt/engine/core/extensions/mgr/ExtensionsManager.java
M backend/manager/modules/pom.xml
M backend/manager/pom.xml
M backend/manager/tools/pom.xml
M 
backend/manager/tools/src/main/modules/org/ovirt/engine/core/tools/main/module.xml
M ovirt-engine.spec.in
A packaging/bin/extensions-tool.sh
16 files changed, 952 insertions(+), 5 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/14/27814/1

diff --git a/backend/manager/extension-tool/pom.xml 
b/backend/manager/extension-tool/pom.xml
new file mode 100644
index 0000000..4d0ffa2
--- /dev/null
+++ b/backend/manager/extension-tool/pom.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0"?>
+
+<project
+  xmlns="http://maven.apache.org/POM/4.0.0";
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.ovirt.engine.core</groupId>
+    <artifactId>manager</artifactId>
+    <version>3.5.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>extension-tool</artifactId>
+  <packaging>jar</packaging>
+  <name>oVirt Engine extensions tool</name>
+  <description>oVirt Engine extensions tools</description>
+
+  <dependencies>
+ <dependency>
+    <groupId>${engine.groupId}</groupId>
+      <artifactId>common</artifactId>
+      <version>${engine.version}</version>
+    </dependency>
+    
+    <dependency>
+      <groupId>${engine.groupId}</groupId>
+      <artifactId>aaa</artifactId>
+      <version>${engine.version}</version>
+    </dependency>
+    
+
+    <dependency>
+      <groupId>${engine.groupId}</groupId>
+      <artifactId>utils</artifactId>
+      <version>${engine.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>commons-configuration</groupId>
+      <artifactId>commons-configuration</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>${junit.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>${engine.groupId}</groupId>
+      <artifactId>extensions-manager</artifactId>
+      <version>${engine.version}</version>
+    </dependency>
+    
+
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <additionalClasspathElements>
+            
<additionalClasspathElement>${basedir}/**/src/test/java</additionalClasspathElement>
+          </additionalClasspathElements>
+          <excludes>
+            <exclude>**/EngineConfigLogicTest.java</exclude>
+            <exclude>**/EngineConfigTest.java</exclude>
+            <exclude>**/MailSenderTest.java</exclude>
+            <exclude>**/StandaloneDataSourceTest.java</exclude>
+            <exclude>**/NotificationServiceTest.java</exclude>
+            <exclude>**/EngineMonitorServiceTest.java</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+
+      <!-- Create the JBoss module: -->
+      <plugin>
+        <groupId>org.ovirt.engine</groupId>
+        <artifactId>jboss-modules-maven-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+
+  <profiles>
+    <profile>
+      <id>enable-tools-itests</id>
+      <dependencies>
+        <dependency>
+          <groupId>postgresql</groupId>
+          <artifactId>postgresql</artifactId>
+          <scope>test</scope>
+        </dependency>
+      </dependencies>
+      <build>
+        <plugins>
+          <plugin>
+            <artifactId>maven-surefire-plugin</artifactId>
+            <configuration combine.self="override">
+              <excludes/>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+        <id>findbugs</id>
+        <activation>
+            <activeByDefault>true</activeByDefault>
+        </activation>
+        <build>
+            <plugins>
+                <plugin>
+                    <groupId>org.codehaus.mojo</groupId>
+                    <artifactId>findbugs-maven-plugin</artifactId>
+                    <version>${findbugs.version}</version>
+                    <configuration>
+                        <xmlOutput>true</xmlOutput>
+                        <!-- Optional directory to put findbugs xdoc xml 
report -->
+                        <excludeFilterFile> 
${basedir}/exclude-filters.xml</excludeFilterFile>
+                        <xmlOutputDirectory>target/site</xmlOutputDirectory>
+                    </configuration>
+                </plugin>
+            </plugins>
+        </build>
+    </profile>
+
+    <profile>
+        <id>findbugs-general</id>
+        <build>
+            <plugins>
+                <plugin>
+                    <groupId>org.codehaus.mojo</groupId>
+                    <artifactId>findbugs-maven-plugin</artifactId>
+                    <version>${findbugs.version}</version>
+                    <configuration>
+                        <xmlOutput>true</xmlOutput>
+                        <!-- Optional directory to put findbugs xdoc xml 
report -->
+                        <excludeFilterFile> ${basedir}/exclude-filters.xml, 
${basedir}/../../../exclude-filters-general.xml</excludeFilterFile>
+                        <xmlOutputDirectory>target/site</xmlOutputDirectory>
+                    </configuration>
+                </plugin>
+            </plugins>
+        </build>
+    </profile>
+  </profiles>
+</project>
diff --git 
a/backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsTool.java
 
b/backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsTool.java
new file mode 100644
index 0000000..3395a50
--- /dev/null
+++ 
b/backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsTool.java
@@ -0,0 +1,292 @@
+package org.ovirt.engine.exttool;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.ovirt.engine.api.extensions.Base;
+import org.ovirt.engine.api.extensions.ExtMap;
+import org.ovirt.engine.api.extensions.ExtUUID;
+import org.ovirt.engine.api.extensions.aaa.Authn;
+import org.ovirt.engine.api.extensions.aaa.Authz;
+import org.ovirt.engine.core.aaa.SearchQueryParsingUtils;
+import org.ovirt.engine.core.extensions.mgr.ExtensionProxy;
+import org.ovirt.engine.core.extensions.mgr.ExtensionsManager;
+
+public class ExtensionsTool {
+
+    private static Logger log = Logger.getLogger(ExtensionsTool.class);
+    private ExtensionProxy authnExtension;
+    private ExtensionsManager extensionsManager;
+
+    public ExtensionsTool(ExtensionsToolArguments args, ExtensionsManager 
extensionsManager) {
+        this.extensionsManager = extensionsManager;
+        try {
+            switch (args.getAction()) {
+            case ExtensionsToolArguments.ACTION_AUTH_SEQUENCE:
+                doAuthSequence(args);
+                break;
+
+            case ExtensionsToolArguments.ACTION_QUERY_BY_IDS:
+                doQueryByIds(args);
+                break;
+
+            case ExtensionsToolArguments.ACTION_QUERY_BY_NAME:
+                doQueryByName(args);
+                break;
+
+            }
+        } catch (Exception ex) {
+            log.error(ex.getMessage());
+            if (log.isDebugEnabled()) {
+                log.debug("", ex);
+            }
+        }
+    }
+
+
+    private void doAuthSequence(ExtensionsToolArguments args) throws Exception 
{
+        String user = null;
+        String password = null;
+        if (args.contains(ExtensionsToolArguments.ARG_USER)) {
+            user = args.get(ExtensionsToolArguments.ARG_USER);
+        } else {
+            System.out.print("Please enter user: ");
+            user = System.console().readLine();
+        }
+
+        if (args.contains(ExtensionsToolArguments.ARG_PASSWORD_ENV_KEY)) {
+            password = 
System.getenv(args.get(ExtensionsToolArguments.ARG_PASSWORD_ENV_KEY));
+        } else if (args.contains(ExtensionsToolArguments.ARG_PASSWORD_FILE)) {
+            try (BufferedReader reader = new BufferedReader(new 
InputStreamReader( new 
FileInputStream(args.get(ExtensionsToolArguments.ARG_PASSWORD_FILE))))) {
+                password = reader.readLine();
+            }
+        } else {
+            System.out.print("Please enter password: ");
+            password = new String(System.console().readPassword());
+        }
+
+        File authnConfig = new File(args.<String> 
get(ExtensionsToolArguments.ARG_AUTHN_NAME));
+        if (!authnConfig.exists()) {
+            throw new Exception("Could not find authn extension configuration 
at the path specified");
+        }
+        authnExtension = 
extensionsManager.activate(extensionsManager.load(authnConfig));
+        ExtMap outMap = authnExtension.invoke(new ExtMap().mput(
+                            Base.InvokeKeys.COMMAND,
+                            Authn.InvokeCommands.AUTHENTICATE_CREDENTIALS
+                        ).mput(
+                                Authn.InvokeKeys.USER,
+                                user
+                                ).mput(
+                                        Authn.InvokeKeys.CREDENTIALS,
+                                        password
+                                       )
+                );
+        ExtMap authRecord = processAuthnResult(outMap, 
"AUTHENTICATE_CREDENTIALS");
+
+        if (args.get(ExtensionsToolArguments.ARG_AUTHZ_NAME) != null) {
+            ExtensionProxy authzExtension = getAuthzExtension(args);
+            if (authzExtension != null) {
+               ExtMap outputMap = authzExtension.invoke(new ExtMap().mput(
+                       Base.InvokeKeys.COMMAND,
+                       Authz.InvokeCommands.FETCH_PRINCIPAL_RECORD).mput(
+                               Authn.InvokeKeys.AUTH_RECORD,
+                                authRecord
+                        )
+                        .mput(
+                                Authz.InvokeKeys.RESOLVE_GROUPS_RECURSIVE,
+                                
Boolean.parseBoolean(args.get(ExtensionsToolArguments.ARG_RESOLVE_GROUPS_RECURSIVE,
 "false"))
+                        )
+                   );
+                printPrincipalRecord(outputMap.<ExtMap> 
get(Authz.InvokeKeys.PRINCIPAL_RECORD));
+                processAuthzResult(outputMap, "FETCH_PRINCIPAL");
+            }
+
+        }
+        if (authRecord != null) {
+            if ((authnExtension.getContext().<Long> 
get(Authn.ContextKeys.CAPABILITIES) & Authn.Capabilities.LOGOUT) != 0) {
+                ExtMap outputMap = authnExtension.invoke(new ExtMap().mput(
+                            Base.InvokeKeys.COMMAND,
+                            Authn.InvokeCommands.LOGOUT
+                        ).mput(
+                                Authn.InvokeKeys.PRINCIPAL,
+                                authRecord.<String> 
get(Authn.AuthRecord.PRINCIPAL)
+                        )
+                );
+                authRecord = processAuthnResult(outputMap, "LOGOUT");
+            }
+            else {
+                log.info("The extension does not support logout");
+            }
+        }
+    }
+
+    private ExtensionProxy getAuthzExtension(ExtensionsToolArguments args) 
throws Exception {
+        File authzConfig = new File(args.<String> 
get(ExtensionsToolArguments.ARG_AUTHZ_NAME));
+        if (!authzConfig.exists()) {
+            throw new Exception("Could not find authz extension configuration 
at the path specified");
+        }
+        return extensionsManager.activate(extensionsManager.load(authzConfig));
+    }
+
+    private ExtMap processAuthnResult(ExtMap outMap, String operation) throws 
Exception {
+        if (outMap.<Integer> get(Base.InvokeKeys.RESULT) != 
Base.InvokeResult.SUCCESS) {
+            throw new Exception(String.format("Base.InvokeResult code is: 
%1$s. Invocation of %2$s failed.",
+                    outMap.<Integer> get(Base.InvokeKeys.RESULT), operation));
+        }
+
+        log.info(String.format("Successful invocation of %1$s", operation));
+        if (outMap.<Integer> get(Authn.InvokeKeys.RESULT) != 
Authn.AuthResult.SUCCESS) {
+            throw new Exception(String.format("Authn.Result code is: %1$s",
+                    outMap.<Integer> get(Authn.InvokeKeys.RESULT)));
+        }
+        printAuthRecord(outMap.<ExtMap> get(Authn.InvokeKeys.AUTH_RECORD));
+        return outMap.get(Authn.InvokeKeys.AUTH_RECORD);
+    }
+
+    private void processAuthzResult(ExtMap outMap, String operation) throws 
Exception {
+        if (outMap.<Integer> get(Base.InvokeKeys.RESULT) != 
Base.InvokeResult.SUCCESS) {
+            throw new Exception(String.format("Base.InvokeResult code is: 
%1$s. Invocation of %2$s failed", outMap.<Integer> get(Base.InvokeKeys.RESULT), 
operation));
+        }
+        log.info(String.format("Successful invocation of %1$s", operation));
+        if (outMap.<Integer> get(Authz.InvokeKeys.STATUS) != 
Authz.Status.SUCCESS) {
+            throw new Exception(String.format("Authz.Status code is: %1$s", 
outMap.<Integer> get(Authz.InvokeKeys.STATUS)));
+        }
+    }
+
+    private void doQueryByName(ExtensionsToolArguments args) throws Exception {
+        runQuery(
+                args,
+                SearchQueryParsingUtils.generateQueryForName(
+                        args.get(ExtensionsToolArguments.ARG_NAME),
+                        getEntityByArgs(args)
+                        )
+                );
+    }
+
+    private void doQueryByIds(ExtensionsToolArguments args) throws Exception {
+        ExtensionProxy authzExtension = getAuthzExtension(args);
+        List<List<String>> idsBatches =
+                SearchQueryParsingUtils.getIdsBatches(authzExtension,
+                        
Arrays.asList(args.get(ExtensionsToolArguments.ARG_IDS, "").split(",")));
+        log.info(String.format("Going to split the ids to %1$s batches for 
execution", idsBatches.size()));
+        ExtUUID entity = getEntityByArgs(args);
+        for (List<String> ids : idsBatches) {
+            runQuery(args,
+                    SearchQueryParsingUtils.generateQueryMap(ids, entity));
+        }
+        log.info("Finished running all queries");
+    }
+
+    private ExtUUID getEntityByArgs(ExtensionsToolArguments args) {
+        return args.get(ExtensionsToolArguments.ARG_QUERY_ENTITY)
+                .equals(ExtensionsToolArguments.QUERY_ENTITY_GROUP) ?
+                Authz.QueryEntity.GROUP : Authz.QueryEntity.PRINCIPAL;
+    }
+
+    private void runQuery(ExtensionsToolArguments args, ExtMap filter) throws 
Exception {
+        ExtUUID entity = getEntityByArgs(args);
+        ExtensionProxy authzExtension = getAuthzExtension(args);
+        ExtMap outMap = authzExtension.invoke(new ExtMap().mput(
+                Base.InvokeKeys.COMMAND,
+                Authz.InvokeCommands.QUERY_OPEN
+                ).mput(
+                        Authz.InvokeKeys.QUERY_ENTITY,
+                        entity
+                ).mput(
+                       Authz.InvokeKeys.RESOLVE_GROUPS_RECURSIVE,
+                       
Boolean.parseBoolean(args.get(ExtensionsToolArguments.ARG_RESOLVE_GROUPS_RECURSIVE,
 "false"))
+                ).mput(
+                        Authz.InvokeKeys.QUERY_FILTER,
+                        filter
+                ));
+        processAuthzResult(outMap, "QueryOpen");
+        if 
(outMap.get(Base.InvokeKeys.RESULT).equals(Base.InvokeResult.SUCCESS)) {
+            do {
+                ExtMap inputMap = new ExtMap().mput(
+                            Base.InvokeKeys.COMMAND,
+                            Authz.InvokeCommands.QUERY_EXECUTE
+                            ).mput(
+                                    Authz.InvokeKeys.QUERY_OPAQUE,
+                                    outMap.get(Authz.InvokeKeys.QUERY_OPAQUE)
+                                  );
+                if (args.contains(ExtensionsToolArguments.ARG_PAGE_SIZE)) {
+                    inputMap.put(Authz.InvokeKeys.PAGE_SIZE,
+                            
Integer.parseInt(args.get(ExtensionsToolArguments.ARG_PAGE_SIZE)));
+                }
+                outMap = authzExtension.invoke(inputMap);
+                processAuthzResult(outMap, "QueryExecute");
+                if 
(outMap.get(Base.InvokeKeys.RESULT).equals(Base.InvokeResult.SUCCESS)) {
+                    List<ExtMap> results = outMap.<List<ExtMap>> 
get(Authz.InvokeKeys.QUERY_RESULT);
+                    if (results != null) {
+                       for (ExtMap result: results) {
+                           if (entity.equals(Authz.QueryEntity.GROUP)) {
+                               printGroupRecord(result);
+                           } else {
+                                printPrincipalRecord(result);
+                           }
+                       }
+                    }
+                }
+
+            } while (outMap.get(Authz.InvokeKeys.QUERY_RESULT) != null);
+            log.info("Finished all executions, closing query");
+            outMap = authzExtension.invoke(new ExtMap().mput(
+                    Base.InvokeKeys.COMMAND,
+                    Authz.InvokeCommands.QUERY_CLOSE
+                    ).mput(
+                            Authz.InvokeKeys.QUERY_OPAQUE,
+                            outMap.get(Authz.InvokeKeys.QUERY_OPAQUE)
+                          ));
+            processAuthzResult(outMap, "QueryClose");
+        }
+    }
+
+    private void printPrincipalRecord(ExtMap extMap) {
+        if (extMap != null) {
+            log.info(String.format("PrincipalRecord: ID %s, name: %s, display 
name: %s, email: %s, first name: %s, last name: %s, department: %s, title: %s",
+                    extMap.get(Authz.PrincipalRecord.ID, ""),
+                    extMap.get(Authz.PrincipalRecord.NAME, ""),
+                    extMap.get(Authz.PrincipalRecord.DISPLAY_NAME, ""),
+                    extMap.get(Authz.PrincipalRecord.EMAIL, ""),
+                    extMap.get(Authz.PrincipalRecord.FIRST_NAME, ""),
+                    extMap.get(Authz.PrincipalRecord.LAST_NAME, ""),
+                    extMap.get(Authz.PrincipalRecord.DEPARTMENT, ""),
+                    extMap.get(Authz.PrincipalRecord.TITLE, "")
+                    ));
+            log.info("Groups of PrincipalRecord: ");
+            for (ExtMap group : extMap.<List<ExtMap>> 
get(Authz.PrincipalRecord.GROUPS,
+                    Collections.<ExtMap> emptyList())) {
+                printGroupRecord(group);
+            }
+            log.info("End of groups of PrincipalRecord: ");
+
+        }
+
+    }
+
+    private void printGroupRecord(ExtMap extMap) {
+        if (extMap != null) {
+            log.info(String.format("GroupRecord: ID %s, name: %s, Display 
name: %s",
+                    extMap.get(Authz.GroupRecord.ID, ""),
+                    extMap.get(Authz.GroupRecord.NAME, ""),
+                    extMap.get(Authz.GroupRecord.DISPLAY_NAME, "")
+                    ));
+        }
+
+    }
+
+    private void printAuthRecord(ExtMap extMap) {
+        if (extMap != null) {
+            log.info(String.format("AuthRecord: Principal %s,  ValidTo: %s",
+                    extMap.get(Authn.AuthRecord.PRINCIPAL, ""),
+                    extMap.get(Authn.AuthRecord.VALID_TO, "")));
+        }
+    }
+
+}
diff --git 
a/backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsToolArguments.java
 
b/backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsToolArguments.java
new file mode 100644
index 0000000..581ec75
--- /dev/null
+++ 
b/backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsToolArguments.java
@@ -0,0 +1,253 @@
+package org.ovirt.engine.exttool;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import org.ovirt.engine.core.uutils.cli.ArgumentBuilder;
+import org.ovirt.engine.core.uutils.cli.ExtendedCliParser;
+
+public class ExtensionsToolArguments {
+
+    private static final String HELP_PROPERTIES = 
"/extensions-tool/help.properties";
+    private String action;
+
+    //LOG
+    public static final String ARG_LOG_LEVEL = "--log-level";
+    public static final String ARG_LOG_FILE = "--log-file";
+    public static final String ARG_LOG4J_CONFIG = "--log4j-config";
+    public static final String ARG_CONFIG_FILE = "--config-file";
+
+    // Actions
+    public static final String ACTION_AUTH_SEQUENCE = "auth-sequence";
+    public static final String ACTION_QUERY_BY_NAME = "query-by-name";
+    public static final String ACTION_QUERY_BY_IDS = "query-by-ids";
+    public static final String ACTION_HELP = "help";
+
+    // Auth arguments
+    public static final String ARG_USER = "--user";
+    public static final String ARG_AUTHN_NAME = "--authn";
+    public static final String ARG_PASSWORD_FILE = "--password-file";
+    public static final String ARG_PASSWORD_ENV_KEY = "--password-env-key";
+
+    // Query arguments
+    public static final String ARG_AUTHZ_NAME = "--authz";
+    public static final String ARG_QUERY_ENTITY = "--query-entity";
+    public static final String ARG_PAGE_SIZE = "--page-size";
+    public static final String ARG_IDS = "--ids";
+    public static final String ARG_NAME = "--name";
+    public static final String ARG_RESOLVE_GROUPS_RECURSIVE = 
"--resolve-groups-recursive";
+    public static final String ARG_MAX_QUERY_RESULTS = "--max-query-results";
+
+    // Query entity values
+    public static final String QUERY_ENTITY_PRINCIPAL = "principal";
+    public static final String QUERY_ENTITY_GROUP = "group";
+
+    private Map<String, String> argMap;
+
+    /**
+     * Returns set of required args for specified action
+     */
+    private Set<String> getRequiredArgs(String action) {
+        Set<String> result = new LinkedHashSet<>();
+
+        if (ACTION_AUTH_SEQUENCE.equals(action)) {
+            result.add(ARG_AUTHN_NAME);
+        } else if (ACTION_QUERY_BY_IDS.equals(action)) {
+            result.add(ARG_IDS);
+            result.add(ARG_PAGE_SIZE);
+            result.add(ARG_AUTHZ_NAME);
+            result.add(ARG_QUERY_ENTITY);
+            result.add(ARG_MAX_QUERY_RESULTS);
+        } else if (ACTION_QUERY_BY_NAME.equals(action)) {
+            result.add(ARG_NAME);
+            result.add(ARG_PAGE_SIZE);
+            result.add(ARG_AUTHZ_NAME);
+            result.add(ARG_QUERY_ENTITY);
+            result.add(ARG_MAX_QUERY_RESULTS);
+        }
+        return result;
+    }
+
+    public void parse(String[] args) throws Exception {
+        if (args.length < 1 || ACTION_HELP.equals(args[0])) {
+            // print help
+            argMap = new HashMap<>();
+            argMap.put(ACTION_HELP, null);
+            return;
+        }
+
+        action = args[0];
+
+        if (!(ACTION_AUTH_SEQUENCE.equals(args[0]) || 
ACTION_QUERY_BY_IDS.equals(args[0]) || ACTION_QUERY_BY_NAME.equals(args[0]))) {
+            throw new Exception("invalid action");
+        }
+
+
+        if (args.length > 1) {
+            // entered more args than just action, parse them
+            ExtendedCliParser parser = initParser(action);
+            argMap = parser.parse(args, 1, args.length);
+        } else {
+            argMap = new HashMap<>();
+        }
+
+        // check that all required args are present
+        for (String arg : getRequiredArgs(args[0])) {
+            if (!argMap.containsKey(arg)) {
+                throw new Exception("Not all required args are present");
+            }
+        }
+    }
+
+    public String get(String key) {
+        return argMap.get(key);
+    }
+
+    public String get(String key, String defaultValue) {
+        return argMap.containsKey(key) ? argMap.get(key) : defaultValue;
+    }
+
+    public void printHelp() {
+        Properties helpProp = new Properties();
+        try (InputStream is = getClass().getResourceAsStream(HELP_PROPERTIES)) 
{
+            helpProp.load(is);
+        } catch (Exception ex) {
+            System.out.println("Error reading help content");
+        }
+        if (!helpProp.isEmpty()) {
+            System.out.println(helpProp.getProperty("help.usage"));
+            System.out.println(helpProp.getProperty("help.actions"));
+            System.out.println(helpProp.getProperty("help.options"));
+        }
+    }
+
+    public boolean contains(String key) {
+        return argMap.containsKey(key);
+    }
+
+    private ExtendedCliParser initParser(String action) {
+        ExtendedCliParser parser = new ExtendedCliParser();
+
+        parser.addArg(new ArgumentBuilder()
+                .longName(ARG_CONFIG_FILE)
+                .valueRequired(true)
+                .build());
+
+        parser.addArg(new ArgumentBuilder()
+                .longName(ARG_LOG_FILE)
+                .valueRequired(true)
+                .build());
+
+        parser.addArg(new ArgumentBuilder()
+                .longName(ARG_LOG_LEVEL)
+                .valueRequired(true)
+                .build());
+
+        parser.addArg(new ArgumentBuilder()
+                .longName(ARG_LOG4J_CONFIG)
+                .valueRequired(true)
+                .build());
+
+        if ((ACTION_AUTH_SEQUENCE.equals(action))) {
+            parser.addArg(new ArgumentBuilder().
+                    longName(ARG_USER).
+                    valueRequired(false).
+                    build());
+
+            parser.addArg(new ArgumentBuilder().
+                    longName(ARG_AUTHN_NAME).
+                    valueRequired(true).
+                    build());
+
+            parser.addArg(new ArgumentBuilder().
+                    longName(ARG_PASSWORD_FILE).
+                    valueRequired(true).
+                    build());
+
+            parser.addArg(new ArgumentBuilder().
+                    longName(ARG_PASSWORD_ENV_KEY).
+                    valueRequired(true).
+                    build());
+
+            parser.addArg(new ArgumentBuilder().
+                    longName(ARG_AUTHZ_NAME).
+                    valueRequired(false).
+                    build());
+
+        } else if (ACTION_QUERY_BY_IDS.equals(action)) {
+            parser.addArg(new ArgumentBuilder().
+                    longName(ARG_IDS).
+                    valueRequired(true).
+                    build());
+
+            parser.addArg(new ArgumentBuilder().
+                    longName(ARG_PAGE_SIZE).
+                    valueRequired(true).
+                    build());
+
+            parser.addArg(new ArgumentBuilder().
+                    longName(ARG_AUTHZ_NAME).
+                    valueRequired(true).
+                    build());
+
+            parser.addArg(new ArgumentBuilder().
+                    longName(ARG_QUERY_ENTITY).
+                    valueRequired(true).
+                    build());
+
+            parser.addArg(new ArgumentBuilder().
+                    longName(ARG_RESOLVE_GROUPS_RECURSIVE).
+                    valueRequired(false).
+                    build());
+
+            parser.addArg(new ArgumentBuilder().
+                    longName(ARG_MAX_QUERY_RESULTS).
+                    valueRequired(true).
+                    build());
+
+        } else if (ACTION_QUERY_BY_NAME.equals(action)) {
+            parser.addArg(new ArgumentBuilder().
+                    longName(ARG_NAME).
+                    valueRequired(true).
+                    build());
+
+            parser.addArg(new ArgumentBuilder().
+                    longName(ARG_PAGE_SIZE).
+                    valueRequired(true).
+                    build());
+
+            parser.addArg(new ArgumentBuilder().
+                    longName(ARG_AUTHZ_NAME).
+                    valueRequired(true).
+                    build());
+
+            parser.addArg(new ArgumentBuilder().
+                    longName(ARG_QUERY_ENTITY).
+                    valueRequired(true).
+                    build());
+
+            parser.addArg(new ArgumentBuilder().
+                    longName(ARG_MAX_QUERY_RESULTS).
+                    valueRequired(true).
+                    build());
+
+            parser.addArg(new ArgumentBuilder().
+                    longName(ARG_RESOLVE_GROUPS_RECURSIVE).
+                    valueRequired(false).
+                    build());
+
+        }
+        return parser;
+    }
+
+    public String getAction() {
+        return action;
+    }
+
+
+
+}
diff --git 
a/backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsToolExecutor.java
 
b/backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsToolExecutor.java
new file mode 100644
index 0000000..285d978
--- /dev/null
+++ 
b/backend/manager/extension-tool/src/main/java/org/ovirt/engine/exttool/ExtensionsToolExecutor.java
@@ -0,0 +1,65 @@
+package org.ovirt.engine.exttool;
+
+
+import static org.ovirt.engine.exttool.ExtensionsToolArguments.ACTION_HELP;
+import static 
org.ovirt.engine.exttool.ExtensionsToolArguments.ARG_LOG4J_CONFIG;
+import static org.ovirt.engine.exttool.ExtensionsToolArguments.ARG_LOG_FILE;
+import static org.ovirt.engine.exttool.ExtensionsToolArguments.ARG_LOG_LEVEL;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.log4j.helpers.LogLog;
+import org.ovirt.engine.core.extensions.mgr.ExtensionsManager;
+import org.ovirt.engine.core.utils.log.Log4jUtils;
+
+public class ExtensionsToolExecutor {
+    public static void setupLogging(String log4jConfig, String logFile, String 
logLevel) {
+        URL cfgFileUrl = null;
+        try {
+            if (log4jConfig == null) {
+                cfgFileUrl = 
ExtensionsToolExecutor.class.getResource("/extensions-tool/log4j.xml");
+            } else {
+                cfgFileUrl = new File(log4jConfig).toURI().toURL();
+            }
+            Log4jUtils.setupLogging(cfgFileUrl);
+        } catch (MalformedURLException ex) {
+            throw new IllegalArgumentException(
+                    String.format("Error loading log4j configuration from 
'%s': %s", cfgFileUrl, ex.getMessage()),
+                    ex);
+        }
+
+        if (logFile != null) {
+            Log4jUtils.addFileAppender(logFile, logLevel);
+        }
+    }
+
+    public static void main(String... args) {
+        ExtensionsToolArguments testerArgs = null;
+        try {
+            // suppress displaying log4j warnings due to accessing logs when 
parsing params
+            LogLog.setQuietMode(true);
+            testerArgs = new ExtensionsToolArguments();
+            testerArgs.parse(args);
+            LogLog.setQuietMode(false);
+
+            setupLogging(testerArgs.get(ARG_LOG4J_CONFIG), 
testerArgs.get(ARG_LOG_FILE), testerArgs.get(ARG_LOG_LEVEL));
+            ExtensionsTool tester = new ExtensionsTool(testerArgs, new 
ExtensionsManager());
+
+        } catch (Throwable t) {
+            System.out.println(t.getMessage());
+            System.exit(1);
+        }
+
+        try {
+            if (testerArgs.contains(ACTION_HELP)) {
+                testerArgs.printHelp();
+                System.exit(0);
+            } else {
+            }
+        } catch (Exception e) {
+        }
+    }
+
+}
diff --git a/backend/manager/extension-tool/src/main/modules/module.xml 
b/backend/manager/extension-tool/src/main/modules/module.xml
new file mode 100644
index 0000000..80a52f8
--- /dev/null
+++ b/backend/manager/extension-tool/src/main/modules/module.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<module xmlns="urn:jboss:module:1.1" name="org.ovirt.engine.core.tools">
+
+  <resources>
+    <resource-root path="tools.jar"/>
+  </resources>
+
+  <dependencies>
+    <module name="javax.api"/>
+    <module name="javax.mail.api"/>
+    <module name="org.apache.commons.collections"/>
+    <module name="org.apache.commons.configuration"/>
+    <module name="org.apache.commons.lang"/>
+    <module name="org.apache.commons.logging"/>
+    <module name="org.apache.log4j"/>
+    <module name="org.ovirt.engine.api.ovirt-engine-extensions-api"/>
+    <module name="org.ovirt.engine.core.aaa"/>
+    <module name="org.ovirt.engine.core.common"/>
+    <module name="org.ovirt.engine.core.compat"/>
+    <module name="org.ovirt.engine.core.extensions-manager"/>
+    <module name="org.ovirt.engine.core.utils"/>
+    <module name="org.ovirt.engine.core.uutils"/>
+    <module name="org.postgresql"/>
+    <module name="org.snmp4j"/>
+    <module name="sun.jdk"/>
+  </dependencies>
+</module>
diff --git 
a/backend/manager/extension-tool/src/main/modules/org/ovirt/engine/core/extension-tool/main/module.xml
 
b/backend/manager/extension-tool/src/main/modules/org/ovirt/engine/core/extension-tool/main/module.xml
new file mode 100644
index 0000000..0a60de8
--- /dev/null
+++ 
b/backend/manager/extension-tool/src/main/modules/org/ovirt/engine/core/extension-tool/main/module.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<module xmlns="urn:jboss:module:1.1" 
name="org.ovirt.engine.core.extension-tool">
+
+  <resources>
+    <resource-root path="extension-tool.jar"/>
+  </resources>
+
+  <dependencies>
+    <module name="javax.api"/>
+    <module name="org.apache.commons.collections"/>
+    <module name="org.apache.commons.configuration"/>
+    <module name="org.apache.commons.lang"/>
+    <module name="org.apache.commons.logging"/>
+    <module name="org.apache.log4j"/>
+    <module name="org.ovirt.engine.api.ovirt-engine-extensions-api"/>
+    <module name="org.ovirt.engine.core.aaa"/>
+    <module name="org.ovirt.engine.core.common"/>
+    <module name="org.ovirt.engine.core.compat"/>
+    <module name="org.ovirt.engine.core.extensions-manager"/>
+    <module name="org.ovirt.engine.core.utils"/>
+    <module name="org.ovirt.engine.core.uutils"/>
+    <module name="sun.jdk"/>
+  </dependencies>
+</module>
diff --git 
a/backend/manager/extension-tool/src/main/resources/extensions-tool/help.properties
 
b/backend/manager/extension-tool/src/main/resources/extensions-tool/help.properties
new file mode 100644
index 0000000..c27d218
--- /dev/null
+++ 
b/backend/manager/extension-tool/src/main/resources/extensions-tool/help.properties
@@ -0,0 +1,59 @@
+help.usage=usage: extensions-tool <action> [<args>]
+
+help.actions=\
+Available actions:\
+\n\tauth-sequence         runs an authentication sequence (authenticate, fetch 
principal, logout)\
+\n\tquery-by-name        queries principal by name \
+\n\tduery-by-ids      queries principals by idss \
+\n\
+\nauth-sequence:\
+\n\textensions-tester auth-sequence  [--user=USER] --authn=AUTHN_CONF_FILE 
[--authz=AUTHZ_CONF_FILE] [--log-file=LOG_FILE] [--log4j-config=LOG4J_XML_FILE] 
[--password-file=PASSWORD_FILE] [--password-env-key=PASSWORD_ENV_KEY]\
+\n\
+\nquery-by-name:\
+\n\textensions-tester query-by-name --authz=AUTHZ_CONF_FILE --name=NAME 
--page-size=PAGE_SIZE --max-query-results=MAX_QUERY_RESULTS 
[--log-file=LOG_FILE] [--log4j-config=LOG4J_XML_FILE] 
[--resolve-groups-recursive=FLAG]\
+\n\
+\nquery-by-ids:\
+\n\textensions-tester query-by-ids -authz=AUTHZ_CONF_FILEE --ids=LIST_OF_IDS 
--page-size=PAGE_SIZE --max-query-results=MAX_QUERY_RESULTS 
[--log-file=LOG_FILE] [--log4j-config=LOG4J_XML_FILE] 
[--resolve-groups-recursive=FLAG]\
+\n\
+
+help.options=\
+\nOptions:\
+\n--user=USER\
+\n\tUser to perform authentication with.\
+\n\
+\n--authn=AUTHN_PROVIDER_NAME\
+\n\tPath to configuration fo authn.\
+\n\
+\n--authz=AUTHZ_CONF_FILE\
+\n\tPath to configuration of authz.\
+\n\
+\n--password-file=PASSWORD_FILE\
+\n\tPath to file the password will be read from, if the argument is provided.\
+\n--log-file=LOG_FILE\
+\n
+\n--password-env-key=PASSWORD_ENV_KEY\
+\n
+\n\tName of environment variable containing the password value, if the 
argument is provided.\
+\n
+\n\tPath to file used for logging.\
+\n\
+\n--log-level=LOG_LEVEL\
+\n\tSets log level, one of DEBUG (default), INFO, WARN, ERROR (case 
insensitive).\
+\n
+\n--log4j-config=LOG4J_XML_FILE\
+\n\tPath to log4j configuration file which logging configuration is loaded 
from.\
+\n\
+\n--help\
+\n\tShow this help message and exit.\
+\n\
+\n--name=NAME\
+\n\tName of principal or group to query.\
+\n\
+\n--ids=IDS\
+\n\tComma delimited string of IDS to query.\
+\n
+\n--log4j-config=LOG4J_XML_FILE\
+\n
+\n\tSets log4j.xml file which logging configuration is loaded from.\
+\n\
+
diff --git 
a/backend/manager/extension-tool/src/main/resources/extensions-tool/jaas.conf 
b/backend/manager/extension-tool/src/main/resources/extensions-tool/jaas.conf
new file mode 100644
index 0000000..69c4b0b
--- /dev/null
+++ 
b/backend/manager/extension-tool/src/main/resources/extensions-tool/jaas.conf
@@ -0,0 +1,4 @@
+EngineKerberosAuth {
+  com.sun.security.auth.module.Krb5LoginModule required client=TRUE;
+};
+
diff --git 
a/backend/manager/extension-tool/src/main/resources/extensions-tool/log4j.xml 
b/backend/manager/extension-tool/src/main/resources/extensions-tool/log4j.xml
new file mode 100644
index 0000000..7b0580b
--- /dev/null
+++ 
b/backend/manager/extension-tool/src/main/resources/extensions-tool/log4j.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/";>
+  <appender name="null-appender" class="org.apache.log4j.varia.NullAppender" />
+  <root>
+    <level value="DEBUG"/>
+    <!--
+      We need this, because log4j writes warning messages to stderr
+      if no appender is configured and we add appender only if proper
+      command line argument is specified.
+    -->
+    <appender-ref ref="null-appender" />
+  </root>
+</log4j:configuration>
diff --git 
a/backend/manager/modules/extensions-manager/src/main/java/org/ovirt/engine/core/extensions/mgr/ExtensionsManager.java
 
b/backend/manager/modules/extensions-manager/src/main/java/org/ovirt/engine/core/extensions/mgr/ExtensionsManager.java
index 4f7f996..0d5a68d 100644
--- 
a/backend/manager/modules/extensions-manager/src/main/java/org/ovirt/engine/core/extensions/mgr/ExtensionsManager.java
+++ 
b/backend/manager/modules/extensions-manager/src/main/java/org/ovirt/engine/core/extensions/mgr/ExtensionsManager.java
@@ -243,7 +243,7 @@
         return results;
     }
 
-    public void activate(String extensionName) {
+    public ExtensionProxy activate(String extensionName) {
         ExtensionEntry entry = loadedEntries.get(extensionName);
         if (entry != null && entry.enabled) {
             entry.extension.getContext().put(
@@ -297,6 +297,7 @@
             dumpConfig(entry.extension);
             setChanged();
             notifyObservers();
+            return entry.extension;
         }
     }
 
diff --git a/backend/manager/modules/pom.xml b/backend/manager/modules/pom.xml
index dd56a22..f410d43 100644
--- a/backend/manager/modules/pom.xml
+++ b/backend/manager/modules/pom.xml
@@ -34,6 +34,7 @@
     <module>services</module>
     <module>docs</module>
     <module>welcome</module>
+    <module>xmlaaa</module>
   </modules>
 
   <dependencies>
diff --git a/backend/manager/pom.xml b/backend/manager/pom.xml
index b743555..b616e0b 100644
--- a/backend/manager/pom.xml
+++ b/backend/manager/pom.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
   <modelVersion>4.0.0</modelVersion>
   <parent>
@@ -14,5 +14,6 @@
     <module>dependencies</module>
     <module>modules</module>
     <module>tools</module>
+    <module>extension-tool</module>
   </modules>
-</project>
+</project>
\ No newline at end of file
diff --git a/backend/manager/tools/pom.xml b/backend/manager/tools/pom.xml
index ee3b340..d49e4ad 100644
--- a/backend/manager/tools/pom.xml
+++ b/backend/manager/tools/pom.xml
@@ -31,6 +31,13 @@
       <artifactId>common</artifactId>
       <version>${engine.version}</version>
     </dependency>
+    
+    <dependency>
+      <groupId>${engine.groupId}</groupId>
+      <artifactId>aaa</artifactId>
+      <version>${engine.version}</version>
+    </dependency>
+    
 
     <dependency>
       <groupId>${engine.groupId}</groupId>
@@ -59,6 +66,12 @@
       <version>${junit.version}</version>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>${engine.groupId}</groupId>
+      <artifactId>extensions-manager</artifactId>
+      <version>${engine.version}</version>
+    </dependency>
+    
 
   </dependencies>
 
diff --git 
a/backend/manager/tools/src/main/modules/org/ovirt/engine/core/tools/main/module.xml
 
b/backend/manager/tools/src/main/modules/org/ovirt/engine/core/tools/main/module.xml
index 47de050..80a52f8 100644
--- 
a/backend/manager/tools/src/main/modules/org/ovirt/engine/core/tools/main/module.xml
+++ 
b/backend/manager/tools/src/main/modules/org/ovirt/engine/core/tools/main/module.xml
@@ -14,13 +14,15 @@
     <module name="org.apache.commons.lang"/>
     <module name="org.apache.commons.logging"/>
     <module name="org.apache.log4j"/>
+    <module name="org.ovirt.engine.api.ovirt-engine-extensions-api"/>
+    <module name="org.ovirt.engine.core.aaa"/>
     <module name="org.ovirt.engine.core.common"/>
     <module name="org.ovirt.engine.core.compat"/>
+    <module name="org.ovirt.engine.core.extensions-manager"/>
     <module name="org.ovirt.engine.core.utils"/>
     <module name="org.ovirt.engine.core.uutils"/>
     <module name="org.postgresql"/>
     <module name="org.snmp4j"/>
     <module name="sun.jdk"/>
   </dependencies>
-
 </module>
diff --git a/ovirt-engine.spec.in b/ovirt-engine.spec.in
index 0f4a915..97ab974 100644
--- a/ovirt-engine.spec.in
+++ b/ovirt-engine.spec.in
@@ -557,7 +557,7 @@
 # /var creation
 #
 install -dm 755 "%{buildroot}/%{engine_state}"/{content,setup/answers}
-install -dm 755 
"%{buildroot}/%{engine_log}"/{host-deploy,setup,notifier,engine-manage-domains,dump}
+install -dm 755 
"%{buildroot}/%{engine_log}"/{host-deploy,setup,notifier,engine-manage-domains,dump,extensions-tool}
 install -dm 755 "%{buildroot}/%{engine_cache}"
 install -dm 755 "%{buildroot}/%{engine_run}/notifier"
 
@@ -595,6 +595,7 @@
 %{engine_jboss_modules}/org/ovirt/engine/core/aaa/main/aaa.jar
 %{engine_jboss_modules}/org/ovirt/engine/core/common/main/common.jar
 %{engine_jboss_modules}/org/ovirt/engine/core/compat/main/compat.jar
+%{engine_jboss_modules}/org/ovirt/engine/core/extension-tool/main/extension-tool.jar
 %{engine_jboss_modules}/org/ovirt/engine/core/dal/main/dal.jar
 
%{engine_jboss_modules}/org/ovirt/engine/core/extensions-manager/main/extensions-manager.jar
 
%{engine_jboss_modules}/org/ovirt/engine/core/searchbackend/main/searchbackend.jar
@@ -1006,6 +1007,7 @@
 %{_bindir}/engine-backup
 %{_bindir}/engine-config
 %{_bindir}/engine-manage-domains
+%{_bindir}/extensions-tool
 %{_mandir}/man8/engine-backup.*
 %{_mandir}/man8/engine-config.*
 %{_mandir}/man8/engine-manage-domains.*
@@ -1013,6 +1015,7 @@
 %{engine_data}/bin/engine-config.sh
 %{engine_data}/bin/engine-manage-domains.sh
 %{engine_data}/bin/engine-prolog.sh
+%{engine_data}/bin/extensions-tool.sh
 %{engine_data}/bin/ovirt-engine-role.sh
 %{engine_data}/conf/jaas.conf
 %{engine_data}/services/ovirt-engine-notifier
diff --git a/packaging/bin/extensions-tool.sh b/packaging/bin/extensions-tool.sh
new file mode 100755
index 0000000..f91c74c
--- /dev/null
+++ b/packaging/bin/extensions-tool.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# This script is designed to run the manage domains utility.
+# The tool's configuration should be under the /etc directory.
+#
+
+# Load the prolog:
+. "$(dirname "$(readlink -f "$0")")"/engine-prolog.sh
+
+#
+# Add this option to the java command line to enable remote debugging in
+# all IP addresses and port 8787:
+#
+# -Xrunjdwp:transport=dt_socket,address=0.0.0.0:8787,server=y,suspend=y
+#
+# Note that the "suspend=y" options is needed to suspend the execution
+# of the JVM till you connect with the debugger, otherwise it is
+# not possible to debug the execution of the main method.
+#
+
+exec "${JAVA_HOME}/bin/java" \
+       -Djboss.modules.write-indexes=false \
+       -jar "${JBOSS_HOME}/jboss-modules.jar" \
+       -dependencies org.ovirt.engine.core.extension-tool \
+       -class org.ovirt.engine.exttool.ExtensionsToolExecutor \
+       "$@"


-- 
To view, visit http://gerrit.ovirt.org/27814
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I7ea2f9c62ced5bdd3801c9f6d8087a35e3c21886
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Yair Zaslavsky <yzasl...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to