You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by jb...@apache.org on 2015/01/14 15:20:22 UTC

[1/2] karaf-cellar git commit: Fix blocking policy display in the cluster:feature-list command

Repository: karaf-cellar
Updated Branches:
  refs/heads/master 3c3ed88f1 -> de97c1eb0


Fix blocking policy display in the cluster:feature-list command


Project: http://git-wip-us.apache.org/repos/asf/karaf-cellar/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf-cellar/commit/aeafa8b9
Tree: http://git-wip-us.apache.org/repos/asf/karaf-cellar/tree/aeafa8b9
Diff: http://git-wip-us.apache.org/repos/asf/karaf-cellar/diff/aeafa8b9

Branch: refs/heads/master
Commit: aeafa8b93db4a6ec9874593ef90f02482caecfb2
Parents: 3c3ed88
Author: Jean-Baptiste Onofré <jb...@apache.org>
Authored: Wed Jan 14 15:04:01 2015 +0100
Committer: Jean-Baptiste Onofré <jb...@apache.org>
Committed: Wed Jan 14 15:04:01 2015 +0100

----------------------------------------------------------------------
 .../apache/karaf/cellar/features/shell/ListFeaturesCommand.java  | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/aeafa8b9/features/src/main/java/org/apache/karaf/cellar/features/shell/ListFeaturesCommand.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/cellar/features/shell/ListFeaturesCommand.java b/features/src/main/java/org/apache/karaf/cellar/features/shell/ListFeaturesCommand.java
index 5816f30..170e1b7 100644
--- a/features/src/main/java/org/apache/karaf/cellar/features/shell/ListFeaturesCommand.java
+++ b/features/src/main/java/org/apache/karaf/cellar/features/shell/ListFeaturesCommand.java
@@ -110,8 +110,8 @@ public class ListFeaturesCommand extends CellarCommandSupport {
                     }
 
                     String blocked = "";
-                    boolean inbound = support.isAllowed(group, Constants.CATEGORY, name + "/" + version, EventType.INBOUND);
-                    boolean outbound = support.isAllowed(group, Constants.CATEGORY, name + "/" + version, EventType.OUTBOUND);
+                    boolean inbound = support.isAllowed(group, Constants.CATEGORY, name, EventType.INBOUND);
+                    boolean outbound = support.isAllowed(group, Constants.CATEGORY, name, EventType.OUTBOUND);
                     if (inbound && outbound && onlyBlocked)
                         continue;
                     if (!inbound && !outbound)


[2/2] karaf-cellar git commit: [KARAF-2241] Add cluster:*-block commands/MBeans operations to display and manage blocking policies

Posted by jb...@apache.org.
[KARAF-2241] Add cluster:*-block commands/MBeans operations to display and manage blocking policies


Project: http://git-wip-us.apache.org/repos/asf/karaf-cellar/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf-cellar/commit/de97c1eb
Tree: http://git-wip-us.apache.org/repos/asf/karaf-cellar/tree/de97c1eb
Diff: http://git-wip-us.apache.org/repos/asf/karaf-cellar/diff/de97c1eb

Branch: refs/heads/master
Commit: de97c1eb06792436e8dbcd8111bb32bef2f8f97f
Parents: aeafa8b
Author: Jean-Baptiste Onofré <jb...@apache.org>
Authored: Wed Jan 14 15:19:41 2015 +0100
Committer: Jean-Baptiste Onofré <jb...@apache.org>
Committed: Wed Jan 14 15:19:41 2015 +0100

----------------------------------------------------------------------
 .../bundle/management/CellarBundleMBean.java    |  13 ++
 .../internal/CellarBundleMBeanImpl.java         |  36 +++++
 .../karaf/cellar/bundle/shell/BlockCommand.java | 135 +++++++++++++++++++
 .../OSGI-INF/blueprint/shell-bundle.xml         |  12 ++
 .../config/management/CellarConfigMBean.java    |  25 ++++
 .../internal/CellarConfigMBeanImpl.java         |  21 +++
 .../karaf/cellar/config/shell/BlockCommand.java | 127 +++++++++++++++++
 .../OSGI-INF/blueprint/shell-config.xml         |  11 ++
 .../apache/karaf/cellar/core/CellarSupport.java |  40 +++++-
 .../management/CellarFeaturesMBean.java         |  13 ++
 .../internal/CellarFeaturesMBeanImpl.java       |  32 ++++-
 .../cellar/features/shell/BlockCommand.java     | 127 +++++++++++++++++
 .../OSGI-INF/blueprint/shell-features.xml       |  11 ++
 13 files changed, 597 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/de97c1eb/bundle/src/main/java/org/apache/karaf/cellar/bundle/management/CellarBundleMBean.java
----------------------------------------------------------------------
diff --git a/bundle/src/main/java/org/apache/karaf/cellar/bundle/management/CellarBundleMBean.java b/bundle/src/main/java/org/apache/karaf/cellar/bundle/management/CellarBundleMBean.java
index 996aa72..58d791d 100644
--- a/bundle/src/main/java/org/apache/karaf/cellar/bundle/management/CellarBundleMBean.java
+++ b/bundle/src/main/java/org/apache/karaf/cellar/bundle/management/CellarBundleMBean.java
@@ -67,6 +67,19 @@ public interface CellarBundleMBean {
     void stop(String group, String id) throws Exception;
 
     /**
+     * Updating blocking policy for a given bundle pattern.
+     *
+     * @param group the cluster group name where to apply the blocking policy.
+     * @param pattern the bundle pattern.
+     * @param whitelist true to allow bundle by updating the whitelist.
+     * @param blacklist true to block bundle by updating the blacklist.
+     * @param in true to update the inbound policy.
+     * @param out true to update the outbound policy.
+     * @throws Exception
+     */
+    void block(String group, String pattern, boolean whitelist, boolean blacklist, boolean in, boolean out) throws Exception;
+
+    /**
      * Get the bundles in a cluster group.
      *
      * @param group the cluster group name.

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/de97c1eb/bundle/src/main/java/org/apache/karaf/cellar/bundle/management/internal/CellarBundleMBeanImpl.java
----------------------------------------------------------------------
diff --git a/bundle/src/main/java/org/apache/karaf/cellar/bundle/management/internal/CellarBundleMBeanImpl.java b/bundle/src/main/java/org/apache/karaf/cellar/bundle/management/internal/CellarBundleMBeanImpl.java
index dc21c19..f962995 100644
--- a/bundle/src/main/java/org/apache/karaf/cellar/bundle/management/internal/CellarBundleMBeanImpl.java
+++ b/bundle/src/main/java/org/apache/karaf/cellar/bundle/management/internal/CellarBundleMBeanImpl.java
@@ -16,6 +16,7 @@ package org.apache.karaf.cellar.bundle.management.internal;
 import org.apache.karaf.cellar.bundle.BundleState;
 import org.apache.karaf.cellar.bundle.ClusterBundleEvent;
 import org.apache.karaf.cellar.bundle.Constants;
+import org.apache.karaf.cellar.bundle.shell.BundleCommandSupport;
 import org.apache.karaf.cellar.core.*;
 import org.apache.karaf.cellar.core.control.ManageGroupAction;
 import org.apache.karaf.cellar.core.control.SwitchStatus;
@@ -330,6 +331,41 @@ public class CellarBundleMBeanImpl extends StandardMBean implements CellarBundle
     }
 
     @Override
+    public void block(String groupName, String bundlePattern, boolean whitelist, boolean blacklist, boolean in, boolean out) throws Exception {
+        List<String> patterns = new ArrayList<String>();
+
+        Map<String, ExtendedBundleState> bundles = gatherBundles(groupName);
+        List<String> selectedBundles = selector(bundlePattern, bundles);
+        for (String selectedBundle : selectedBundles) {
+            patterns.add(bundles.get(selectedBundle).getLocation());
+        }
+
+        if (patterns.isEmpty()) {
+            patterns.add(bundlePattern);
+        }
+
+        CellarSupport support = new CellarSupport();
+        support.setClusterManager(clusterManager);
+        support.setGroupManager(groupManager);
+        support.setConfigurationAdmin(configurationAdmin);
+
+        for (String pattern : patterns) {
+            if (in) {
+                if (whitelist)
+                    support.switchListEntry(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.INBOUND, pattern);
+                if (blacklist)
+                    support.switchListEntry(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.INBOUND, pattern);
+            }
+            if (out) {
+                if (whitelist)
+                    support.switchListEntry(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.OUTBOUND, pattern);
+                if (blacklist)
+                    support.switchListEntry(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.OUTBOUND, pattern);
+            }
+        }
+    }
+
+    @Override
     public TabularData getBundles(String groupName) throws Exception {
         CompositeType compositeType = new CompositeType("Bundle", "Karaf Cellar bundle",
                 new String[]{"id", "name", "version", "status", "location", "located", "blocked"},

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/de97c1eb/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/BlockCommand.java
----------------------------------------------------------------------
diff --git a/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/BlockCommand.java b/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/BlockCommand.java
new file mode 100644
index 0000000..8096716
--- /dev/null
+++ b/bundle/src/main/java/org/apache/karaf/cellar/bundle/shell/BlockCommand.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed 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.karaf.cellar.bundle.shell;
+
+import org.apache.karaf.cellar.bundle.Constants;
+import org.apache.karaf.cellar.core.CellarSupport;
+import org.apache.karaf.cellar.core.Configurations;
+import org.apache.karaf.cellar.core.Group;
+import org.apache.karaf.cellar.core.event.EventType;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+
+import java.util.*;
+
+@Command(scope = "cluster", name = "bundle-block", description = "Change the blocking policy for a bundle")
+public class BlockCommand extends BundleCommandSupport {
+
+    @Option(name = "-in", description = "Update the inbound direction", required = false, multiValued = false)
+    boolean in = false;
+
+    @Option(name = "-out", description = "Update the outbound direction", required = false, multiValued = false)
+    boolean out = false;
+
+    @Option(name = "-whitelist", description = "Allow the feature by updating the whitelist (false by default)", required = false, multiValued = false)
+    boolean whitelist = false;
+
+    @Option(name = "-blacklist", description = "Block the feature by updating the blacklist (true by default)", required = false, multiValued = false)
+    boolean blacklist = false;
+
+    public Object doExecute() throws Exception {
+
+        Group group = groupManager.findGroupByName(groupName);
+        if (group == null) {
+            System.err.println("Cluster group " + groupName + " doesn't exist");
+            return null;
+        }
+
+        List<String> patterns = new ArrayList<String>();
+
+        Map<String, ExtendedBundleState> bundles = gatherBundles();
+        List<String> selectedBundles = selector(bundles);
+        for (String selectedBundle : selectedBundles) {
+            patterns.add(bundles.get(selectedBundle).getLocation());
+        }
+
+        if (patterns.isEmpty()) {
+            for (String id : ids) {
+                patterns.add(id);
+            }
+        }
+
+        CellarSupport support = new CellarSupport();
+        support.setClusterManager(clusterManager);
+        support.setGroupManager(groupManager);
+        support.setConfigurationAdmin(configurationAdmin);
+
+        if (!in && !out) {
+            in = true;
+            out = true;
+        }
+        if (!whitelist && !blacklist) {
+            whitelist = true;
+            blacklist = true;
+        }
+
+        if (patterns.isEmpty()) {
+            // display mode
+            if (in) {
+                System.out.println("INBOUND:");
+                if (whitelist) {
+                    System.out.print("\twhitelist: ");
+                    Set<String> list = support.getListEntries(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.INBOUND);
+                    System.out.println(list.toString());
+                }
+                if (blacklist) {
+                    System.out.print("\tblacklist: ");
+                    Set<String> list = support.getListEntries(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.INBOUND);
+                    System.out.println(list.toString());
+                }
+            }
+            if (out) {
+                System.out.println("OUTBOUND:");
+                if (whitelist) {
+                    System.out.print("\twhitelist: ");
+                    Set<String> list = support.getListEntries(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.OUTBOUND);
+                    System.out.println(list.toString());
+                }
+                if (blacklist) {
+                    System.out.print("\tblacklist: ");
+                    Set<String> list = support.getListEntries(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.OUTBOUND);
+                    System.out.println(list.toString());
+                }
+            }
+        } else {
+            // edit mode
+            for (String pattern : patterns) {
+                System.out.println("Updating blocking policy for " + pattern);
+                if (in) {
+                    if (whitelist) {
+                        System.out.println("\tinbound whitelist ...");
+                        support.switchListEntry(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.INBOUND, pattern);
+                    }
+                    if (blacklist) {
+                        System.out.println("\tinbound blacklist ...");
+                        support.switchListEntry(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.INBOUND, pattern);
+                    }
+                }
+                if (out) {
+                    if (whitelist) {
+                        System.out.println("\toutbound whitelist ...");
+                        support.switchListEntry(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.OUTBOUND, pattern);
+                    }
+                    if (blacklist) {
+                        System.out.println("\toutbound blacklist ...");
+                        support.switchListEntry(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.OUTBOUND, pattern);
+                    }
+                }
+            }
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/de97c1eb/bundle/src/main/resources/OSGI-INF/blueprint/shell-bundle.xml
----------------------------------------------------------------------
diff --git a/bundle/src/main/resources/OSGI-INF/blueprint/shell-bundle.xml b/bundle/src/main/resources/OSGI-INF/blueprint/shell-bundle.xml
index 2ca4cad..f8862e8 100644
--- a/bundle/src/main/resources/OSGI-INF/blueprint/shell-bundle.xml
+++ b/bundle/src/main/resources/OSGI-INF/blueprint/shell-bundle.xml
@@ -75,6 +75,18 @@
                 <ref component-id="allBundlesVersionCompleter"/>
             </completers>
         </command>
+        <command>
+            <action class="org.apache.karaf.cellar.bundle.shell.BlockCommand">
+                <property name="clusterManager" ref="clusterManager"/>
+                <property name="groupManager" ref="groupManager"/>
+                <property name="configurationAdmin" ref="configurationAdmin"/>
+            </action>
+            <completers>
+                <ref component-id="allGroupsCompleter"/>
+                <ref component-id="allBundlesNameCompleter"/>
+                <ref component-id="allBundlesVersionCompleter"/>
+            </completers>
+        </command>
     </command-bundle>
 
     <bean id="allGroupsCompleter" class="org.apache.karaf.cellar.core.shell.completer.AllGroupsCompleter">

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/de97c1eb/config/src/main/java/org/apache/karaf/cellar/config/management/CellarConfigMBean.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/cellar/config/management/CellarConfigMBean.java b/config/src/main/java/org/apache/karaf/cellar/config/management/CellarConfigMBean.java
index 5a9a1f8..9af6e23 100644
--- a/config/src/main/java/org/apache/karaf/cellar/config/management/CellarConfigMBean.java
+++ b/config/src/main/java/org/apache/karaf/cellar/config/management/CellarConfigMBean.java
@@ -82,8 +82,33 @@ public interface CellarConfigMBean {
      */
     void deleteProperty(String group, String pid, String key) throws Exception;
 
+    /**
+     * Get the list of config properties excluded from the sync.
+     *
+     * @return the properties excluded from the sync.
+     * @throws Exception
+     */
     String getExcludedProperties() throws Exception;
 
+    /**
+     * Define the list of config properties excluded from the sync.
+     *
+     * @param excludedProperties the properties excluded from the sync.
+     * @throws Exception
+     */
     void setExcludedProperties(String excludedProperties) throws Exception;
 
+    /**
+     * Change the blocking policy for the given config PID pattern.
+     *
+     * @param groupName the cluster group name.
+     * @param pid the config PID pattern.
+     * @param whitelist true to allow the PID pattern by updating the whitelist.
+     * @param blacklist true to block the PID pattern by updating the blacklist.
+     * @param in true to change inbound blocking policy.
+     * @param out true to change outbound blocking policy.
+     * @throws Exception
+     */
+    void block(String groupName, String pid, boolean whitelist, boolean blacklist, boolean in, boolean out) throws Exception;
+
 }

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/de97c1eb/config/src/main/java/org/apache/karaf/cellar/config/management/internal/CellarConfigMBeanImpl.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/cellar/config/management/internal/CellarConfigMBeanImpl.java b/config/src/main/java/org/apache/karaf/cellar/config/management/internal/CellarConfigMBeanImpl.java
index 607db9f..d6101b3 100644
--- a/config/src/main/java/org/apache/karaf/cellar/config/management/internal/CellarConfigMBeanImpl.java
+++ b/config/src/main/java/org/apache/karaf/cellar/config/management/internal/CellarConfigMBeanImpl.java
@@ -267,6 +267,27 @@ public class CellarConfigMBeanImpl extends StandardMBean implements CellarConfig
         }
     }
 
+    @Override
+    public void block(String groupName, String pid, boolean whitelist, boolean blacklist, boolean in, boolean out) throws Exception {
+        CellarSupport support = new CellarSupport();
+        support.setClusterManager(clusterManager);
+        support.setGroupManager(groupManager);
+        support.setConfigurationAdmin(configurationAdmin);
+
+        if (in) {
+            if (whitelist)
+                support.switchListEntry(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.INBOUND, pid);
+            if (blacklist)
+                support.switchListEntry(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.INBOUND, pid);
+        }
+        if (out) {
+            if (whitelist)
+                support.switchListEntry(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.OUTBOUND, pid);
+            if (blacklist)
+                support.switchListEntry(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.OUTBOUND, pid);
+        }
+    }
+
     public ClusterManager getClusterManager() {
         return this.clusterManager;
     }

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/de97c1eb/config/src/main/java/org/apache/karaf/cellar/config/shell/BlockCommand.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/cellar/config/shell/BlockCommand.java b/config/src/main/java/org/apache/karaf/cellar/config/shell/BlockCommand.java
new file mode 100644
index 0000000..977025e
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/cellar/config/shell/BlockCommand.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed 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.karaf.cellar.config.shell;
+
+import org.apache.karaf.cellar.config.Constants;
+import org.apache.karaf.cellar.core.CellarSupport;
+import org.apache.karaf.cellar.core.Configurations;
+import org.apache.karaf.cellar.core.Group;
+import org.apache.karaf.cellar.core.event.EventType;
+import org.apache.karaf.cellar.core.shell.CellarCommandSupport;
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+
+import java.util.Set;
+
+@Command(scope = "cluster", name = "config-block", description = "Change the blocking policy for a bundle")
+public class BlockCommand extends CellarCommandSupport {
+
+    @Argument(index = 0, name = "group", description = "The cluster group name", required = true, multiValued = false)
+    String groupName;
+
+    @Argument(index = 1, name = "pidPattern", description = "The configuration PID pattern", required = false, multiValued = false)
+    String pid;
+
+    @Option(name = "-in", description = "Update the inbound direction", required = false, multiValued = false)
+    boolean in = false;
+
+    @Option(name = "-out", description = "Update the outbound direction", required = false, multiValued = false)
+    boolean out = false;
+
+    @Option(name = "-whitelist", description = "Allow the feature by updating the whitelist (false by default)", required = false, multiValued = false)
+    boolean whitelist = false;
+
+    @Option(name = "-blacklist", description = "Block the feature by updating the blacklist (true by default)", required = false, multiValued = false)
+    boolean blacklist = false;
+
+    public Object doExecute() throws Exception {
+
+        Group group = groupManager.findGroupByName(groupName);
+        if (group == null) {
+            System.err.println("Cluster group " + groupName + " doesn't exist");
+            return null;
+        }
+
+        CellarSupport support = new CellarSupport();
+        support.setClusterManager(clusterManager);
+        support.setGroupManager(groupManager);
+        support.setConfigurationAdmin(configurationAdmin);
+
+        if (!in && !out) {
+            in = true;
+            out = true;
+        }
+        if (!whitelist && !blacklist) {
+            whitelist = true;
+            blacklist = true;
+        }
+
+        if (pid == null || pid.isEmpty()) {
+            // display mode
+            if (in) {
+                System.out.println("INBOUND:");
+                if (whitelist) {
+                    System.out.print("\twhitelist: ");
+                    Set<String> list = support.getListEntries(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.INBOUND);
+                    System.out.println(list.toString());
+                }
+                if (blacklist) {
+                    System.out.print("\tblacklist: ");
+                    Set<String> list = support.getListEntries(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.INBOUND);
+                    System.out.println(list.toString());
+                }
+            }
+            if (out) {
+                System.out.println("OUTBOUND:");
+                if (whitelist) {
+                    System.out.print("\twhitelist: ");
+                    Set<String> list = support.getListEntries(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.OUTBOUND);
+                    System.out.println(list.toString());
+                }
+                if (blacklist) {
+                    System.out.print("\tblacklist: ");
+                    Set<String> list = support.getListEntries(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.OUTBOUND);
+                    System.out.println(list.toString());
+                }
+            }
+        } else {
+            // edit mode
+            System.out.println("Updating blocking policy for " + pid);
+            if (in) {
+                if (whitelist) {
+                    System.out.println("\tinbound whitelist ...");
+                    support.switchListEntry(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.INBOUND, pid);
+                }
+                if (blacklist) {
+                    System.out.println("\tinbound blacklist ...");
+                    support.switchListEntry(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.INBOUND, pid);
+                }
+            }
+            if (out) {
+                if (whitelist) {
+                    System.out.println("\toutbound whitelist ...");
+                    support.switchListEntry(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.OUTBOUND, pid);
+                }
+                if (blacklist) {
+                    System.out.println("\toutbound blacklist ...");
+                    support.switchListEntry(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.OUTBOUND, pid);
+                }
+            }
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/de97c1eb/config/src/main/resources/OSGI-INF/blueprint/shell-config.xml
----------------------------------------------------------------------
diff --git a/config/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/config/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index fc8a0ad..82ad3c3 100644
--- a/config/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/config/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -90,6 +90,17 @@
                 <property name="configurationAdmin" ref="configurationAdmin"/>
             </action>
         </command>
+        <command>
+            <action class="org.apache.karaf.cellar.config.shell.BlockCommand">
+                <property name="clusterManager" ref="clusterManager"/>
+                <property name="groupManager" ref="groupManager"/>
+                <property name="configurationAdmin" ref="configurationAdmin"/>
+            </action>
+            <completers>
+                <ref component-id="allGroupsCompleter"/>
+                <ref component-id="clusterConfigCompleter"/>
+            </completers>
+        </command>
     </command-bundle>
 
     <bean id="allGroupsCompleter" class="org.apache.karaf.cellar.core.shell.completer.AllGroupsCompleter">

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/de97c1eb/core/src/main/java/org/apache/karaf/cellar/core/CellarSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/karaf/cellar/core/CellarSupport.java b/core/src/main/java/org/apache/karaf/cellar/core/CellarSupport.java
index a7cfa85..b597e97 100644
--- a/core/src/main/java/org/apache/karaf/cellar/core/CellarSupport.java
+++ b/core/src/main/java/org/apache/karaf/cellar/core/CellarSupport.java
@@ -20,10 +20,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
-import java.util.Collection;
-import java.util.Dictionary;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -39,6 +36,41 @@ public class CellarSupport {
     protected ConfigurationAdmin configurationAdmin;
 
     /**
+     * If the entry is not present in the list, add it. If the entry is present in the list, remove it.
+     *
+     * @param listType the comma separated list of resources.
+     * @param group the cluster group name.
+     * @param category the resource category name.
+     * @param entry the entry to switch.
+     */
+    public void switchListEntry(String listType, String group, String category, EventType type, String entry) throws Exception {
+        if (group != null) {
+            Configuration configuration = configurationAdmin.getConfiguration(Configurations.GROUP, null);
+            Dictionary dictionary = configuration.getProperties();
+            if (dictionary == null) {
+                dictionary = new Properties();
+            }
+            String key = group + Configurations.SEPARATOR + category + Configurations.SEPARATOR + listType + Configurations.SEPARATOR + type.name().toLowerCase();
+            if (dictionary.get(key) != null) {
+                String value = dictionary.get(key).toString();
+                if (value.contains(entry)) {
+                    value = value.replace(entry, "");
+                } else {
+                    value = value + "," + entry;
+                }
+                if (value.startsWith(",")) value = value.substring(1);
+                if (value.endsWith(",")) value = value.substring(0, value.length() - 1);
+                value = value.replace("\n\n", "");
+                value = value.replace(",,", ",");
+                dictionary.put(key, value);
+            } else {
+                dictionary.put(key, entry);
+            }
+            configuration.update(dictionary);
+        }
+    }
+
+    /**
      * Get a set of resources in the Cellar cluster groups configuration.
      *
      * @param listType the comma separated list of resources.

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/de97c1eb/features/src/main/java/org/apache/karaf/cellar/features/management/CellarFeaturesMBean.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/cellar/features/management/CellarFeaturesMBean.java b/features/src/main/java/org/apache/karaf/cellar/features/management/CellarFeaturesMBean.java
index 605391f..54f6482 100644
--- a/features/src/main/java/org/apache/karaf/cellar/features/management/CellarFeaturesMBean.java
+++ b/features/src/main/java/org/apache/karaf/cellar/features/management/CellarFeaturesMBean.java
@@ -167,6 +167,19 @@ public interface CellarFeaturesMBean {
     void uninstallFeature(String group, String name, String version, boolean noRefresh) throws Exception;
 
     /**
+     * Change the blocking policy for a feature pattern.
+     *
+     * @param group the cluster group name.
+     * @param pattern the feature pattern.
+     * @param whitelist true to allow the feature by updating the whitelist.
+     * @param blacklist true to block the feature by updating the blacklist
+     * @param in true to change the inbound blocking policy.
+     * @param out true to change the outbound blocking policy.
+     * @throws Exception
+     */
+    void block(String group, String pattern, boolean whitelist, boolean blacklist, boolean in, boolean out) throws Exception;
+
+    /**
      * Get the list of features repository URLs in a cluster group.
      *
      * @param group the cluster group name.

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/de97c1eb/features/src/main/java/org/apache/karaf/cellar/features/management/internal/CellarFeaturesMBeanImpl.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/cellar/features/management/internal/CellarFeaturesMBeanImpl.java b/features/src/main/java/org/apache/karaf/cellar/features/management/internal/CellarFeaturesMBeanImpl.java
index cbc054f..6e354d3 100644
--- a/features/src/main/java/org/apache/karaf/cellar/features/management/internal/CellarFeaturesMBeanImpl.java
+++ b/features/src/main/java/org/apache/karaf/cellar/features/management/internal/CellarFeaturesMBeanImpl.java
@@ -309,8 +309,8 @@ public class CellarFeaturesMBeanImpl extends StandardMBean implements CellarFeat
                         located = "local";
 
                     String blocked = "";
-                    boolean inbound = support.isAllowed(group, Constants.CATEGORY, feature.getName() + "/" + feature.getVersion(), EventType.INBOUND);
-                    boolean outbound = support.isAllowed(group, Constants.CATEGORY, feature.getName() + "/" + feature.getVersion(), EventType.OUTBOUND);
+                    boolean inbound = support.isAllowed(group, Constants.CATEGORY, feature.getName(), EventType.INBOUND);
+                    boolean outbound = support.isAllowed(group, Constants.CATEGORY, feature.getName(), EventType.OUTBOUND);
                     if (!inbound && !outbound)
                         blocked = "in/out";
                     if (!inbound && outbound)
@@ -559,6 +559,34 @@ public class CellarFeaturesMBeanImpl extends StandardMBean implements CellarFeat
         }
     }
 
+    @Override
+    public void block(String groupName, String featurePattern, boolean whitelist, boolean blacklist, boolean in, boolean out) throws Exception {
+
+        Group group = groupManager.findGroupByName(groupName);
+        if (group == null) {
+            throw new IllegalArgumentException("Cluster group " + groupName + " doesn't exist");
+        }
+
+        CellarSupport support = new CellarSupport();
+        support.setClusterManager(clusterManager);
+        support.setGroupManager(groupManager);
+        support.setConfigurationAdmin(configurationAdmin);
+
+        if (in) {
+            if (whitelist)
+                support.switchListEntry(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.INBOUND, featurePattern);
+            if (blacklist)
+                support.switchListEntry(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.INBOUND, featurePattern);
+        }
+        if (out) {
+            if (whitelist)
+                support.switchListEntry(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.OUTBOUND, featurePattern);
+            if (blacklist)
+                support.switchListEntry(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.OUTBOUND, featurePattern);
+        }
+
+    }
+
     class ExtendedFeatureState extends FeatureState {
 
         private boolean cluster;

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/de97c1eb/features/src/main/java/org/apache/karaf/cellar/features/shell/BlockCommand.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/cellar/features/shell/BlockCommand.java b/features/src/main/java/org/apache/karaf/cellar/features/shell/BlockCommand.java
new file mode 100644
index 0000000..cf9143d
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/cellar/features/shell/BlockCommand.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed 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.karaf.cellar.features.shell;
+
+import org.apache.karaf.cellar.core.CellarSupport;
+import org.apache.karaf.cellar.core.Configurations;
+import org.apache.karaf.cellar.core.Group;
+import org.apache.karaf.cellar.core.event.EventType;
+import org.apache.karaf.cellar.core.shell.CellarCommandSupport;
+import org.apache.karaf.cellar.features.Constants;
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+
+import java.util.Set;
+
+@Command(scope = "cluster", name = "feature-block", description = "Change the blocking policy for a feature")
+public class BlockCommand extends CellarCommandSupport {
+
+    @Argument(index = 0, name = "group", description = "The cluster group name", required = true, multiValued = false)
+    String groupName;
+
+    @Argument(index = 1, name = "featurePattern", description = "The feature pattern to block.", required = false, multiValued = false)
+    String featurePattern;
+
+    @Option(name = "-in", description = "Update the inbound direction", required = false, multiValued = false)
+    boolean in = false;
+
+    @Option(name = "-out", description = "Update the outbound direction", required = false, multiValued = false)
+    boolean out = false;
+
+    @Option(name = "-whitelist", description = "Allow the feature by updating the whitelist", required = false, multiValued = false)
+    boolean whitelist = false;
+
+    @Option(name = "-blacklist", description = "Block the feature by updating the blacklist", required = false, multiValued = false)
+    boolean blacklist = false;
+
+    public Object doExecute() throws Exception {
+
+        Group group = groupManager.findGroupByName(groupName);
+        if (group == null) {
+            System.err.println("Cluster group " + groupName + " doesn't exist");
+            return null;
+        }
+
+        CellarSupport support = new CellarSupport();
+        support.setClusterManager(clusterManager);
+        support.setGroupManager(groupManager);
+        support.setConfigurationAdmin(configurationAdmin);
+
+        if (!in && !out) {
+            in = true;
+            out = true;
+        }
+        if (!whitelist && !blacklist) {
+            whitelist = true;
+            blacklist = true;
+        }
+
+        if (featurePattern == null || featurePattern.isEmpty()) {
+            // display mode
+            if (in) {
+                System.out.println("INBOUND:");
+                if (whitelist) {
+                    System.out.print("\twhitelist: ");
+                    Set<String> list = support.getListEntries(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.INBOUND);
+                    System.out.println(list.toString());
+                }
+                if (blacklist) {
+                    System.out.print("\tblacklist: ");
+                    Set<String> list = support.getListEntries(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.INBOUND);
+                    System.out.println(list.toString());
+                }
+            }
+            if (out) {
+                System.out.println("OUTBOUND:");
+                if (whitelist) {
+                    System.out.print("\twhitelist: ");
+                    Set<String> list = support.getListEntries(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.OUTBOUND);
+                    System.out.println(list.toString());
+                }
+                if (blacklist) {
+                    System.out.print("\tblacklist: ");
+                    Set<String> list = support.getListEntries(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.OUTBOUND);
+                    System.out.println(list.toString());
+                }
+            }
+        } else {
+            // edit mode
+            System.out.println("Updating blocking policy for " + featurePattern);
+            if (in) {
+                if (whitelist) {
+                    System.out.println("\tinbound whitelist ...");
+                    support.switchListEntry(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.INBOUND, featurePattern);
+                }
+                if (blacklist) {
+                    System.out.println("\tinbound blacklist ...");
+                    support.switchListEntry(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.INBOUND, featurePattern);
+                }
+            }
+            if (out) {
+                if (whitelist) {
+                    System.out.println("\toutbound whitelist ...");
+                    support.switchListEntry(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.OUTBOUND, featurePattern);
+                }
+                if (blacklist) {
+                    System.out.println("\toutbound blacklist ...");
+                    support.switchListEntry(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.OUTBOUND, featurePattern);
+                }
+            }
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf-cellar/blob/de97c1eb/features/src/main/resources/OSGI-INF/blueprint/shell-features.xml
----------------------------------------------------------------------
diff --git a/features/src/main/resources/OSGI-INF/blueprint/shell-features.xml b/features/src/main/resources/OSGI-INF/blueprint/shell-features.xml
index 9b70226..dac31cf 100644
--- a/features/src/main/resources/OSGI-INF/blueprint/shell-features.xml
+++ b/features/src/main/resources/OSGI-INF/blueprint/shell-features.xml
@@ -84,6 +84,17 @@
                 <ref component-id="allGroupsCompleter"/>
             </completers>
         </command>
+        <command>
+            <action class="org.apache.karaf.cellar.features.shell.BlockCommand">
+                <property name="clusterManager" ref="clusterManager"/>
+                <property name="groupManager" ref="groupManager"/>
+                <property name="configurationAdmin" ref="configurationAdmin"/>
+            </action>
+            <completers>
+                <ref component-id="allGroupsCompleter"/>
+                <ref component-id="allFeaturesCompleter"/>
+            </completers>
+        </command>
     </command-bundle>
 
     <bean id="allGroupsCompleter" class="org.apache.karaf.cellar.core.shell.completer.AllGroupsCompleter">