diff options
author | subhash kumar singh <subhash.kumar.singh@huawei.com> | 2017-12-21 14:06:08 +0000 |
---|---|---|
committer | subhash kumar singh <subhash.kumar.singh@huawei.com> | 2018-01-31 05:01:22 +0000 |
commit | d701b812258d0e84a5d5cce0296b004e364a1a3b (patch) | |
tree | 182240c7531ab3dd8167b3538290171301b8347c /profiles | |
parent | a158de7f4f197d65adc7332bd3ad59fb1203a085 (diff) |
Add snmp profile for cli
Add snmp profile for cli to support snmp get operation.
Issue-ID: CLI-85
Change-Id: I7bebd38f2b3089df80c71a5581b23c5408c6d3ab
Signed-off-by: subhash kumar singh <subhash.kumar.singh@huawei.com>
Diffstat (limited to 'profiles')
12 files changed, 550 insertions, 0 deletions
diff --git a/profiles/pom.xml b/profiles/pom.xml index 5e6d00af..8dc2dd7e 100644 --- a/profiles/pom.xml +++ b/profiles/pom.xml @@ -33,6 +33,7 @@ <modules> <module>http</module> + <module>snmp</module> </modules> <dependencies> <dependency> diff --git a/profiles/snmp/pom.xml b/profiles/snmp/pom.xml new file mode 100644 index 00000000..75d5434b --- /dev/null +++ b/profiles/snmp/pom.xml @@ -0,0 +1,50 @@ +<?xml version="1.0"?> +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.onap.cli</groupId> + <artifactId>cli-profiles</artifactId> + <version>2.0.0</version> + </parent> + + <artifactId>cli-profiles-snmp</artifactId> + <name>cli/profiles/snmp</name> + <packaging>jar</packaging> + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + <dependencies> + <dependency> + <groupId>org.snmp4j</groupId> + <artifactId>snmp4j</artifactId> + <version>2.5.6</version> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.11</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.jmockit</groupId> + <artifactId>jmockit</artifactId> + <version>1.19</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.jmockit</groupId> + <artifactId>jmockit-coverage</artifactId> + <version>1.19</version> + <scope>test</scope> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + </plugin> + </plugins> + </build> +</project> diff --git a/profiles/snmp/src/main/java/org/onap/cli/fw/snmp/cmd/OnapSnmpCommand.java b/profiles/snmp/src/main/java/org/onap/cli/fw/snmp/cmd/OnapSnmpCommand.java new file mode 100644 index 00000000..cf2d91d0 --- /dev/null +++ b/profiles/snmp/src/main/java/org/onap/cli/fw/snmp/cmd/OnapSnmpCommand.java @@ -0,0 +1,185 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * 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.onap.cli.fw.snmp.cmd; + +import org.onap.cli.fw.cmd.OnapCommand; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.input.OnapCommandParameter; +import org.onap.cli.fw.schema.OnapCommandSchema; +import org.onap.cli.fw.snmp.conf.OnapCommandSnmpConstants; +import org.onap.cli.fw.snmp.exception.OnapSnmpErrorResponse; +import org.onap.cli.fw.snmp.schema.OnapCommandSchemaSnmpLoader; +import org.snmp4j.CommunityTarget; +import org.snmp4j.PDU; +import org.snmp4j.Snmp; +import org.snmp4j.Target; +import org.snmp4j.event.ResponseEvent; +import org.snmp4j.mp.SnmpConstants; +import org.snmp4j.smi.Address; +import org.snmp4j.smi.GenericAddress; +import org.snmp4j.smi.OID; +import org.snmp4j.smi.OctetString; +import org.snmp4j.smi.VariableBinding; +import org.snmp4j.transport.DefaultUdpTransportMapping; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Vector; + +/** + * Oclip snmp Command. + * + */ +@OnapCommandSchema(type = OnapCommandSnmpConstants.SNMP_SCHEMA_PROFILE) +public class OnapSnmpCommand extends OnapCommand { + + private List<Map<String, String>> resultMap; + + private String version; + + private String command; + + public OnapSnmpCommand() { + super.addDefaultSchemas(OnapCommandSnmpConstants.DEFAULT_PARAMETER_SNMP_FILE_NAME); + } + + private String getAgent() throws OnapCommandException { + OnapCommandParameter onapCommandParameter = this.getParametersMap().get(OnapCommandSnmpConstants.SNMP_AGENT); + return (String) onapCommandParameter.getValue(); + } + + private PDU getPDU(Integer commandType, String[] oids) { + PDU pdu = new PDU(); + for (String oid: oids) { + pdu.add(new VariableBinding(new OID(oid))); + } + + pdu.setType(commandType); + return pdu; + } + + private Target getTarget() throws OnapCommandException { + Address targetAddress = GenericAddress.parse(this.getAgent()); //udp:127.0.0.1/161 + CommunityTarget target = new CommunityTarget(); + target.setCommunity(new OctetString(OnapCommandSnmpConstants.SNMP_COMMNUNITY_STRING)); + target.setAddress(targetAddress); + target.setRetries(OnapCommandSnmpConstants.RETRY_COUNT); + target.setTimeout(OnapCommandSnmpConstants.TIMEOUT); + + switch (this.getSnmpVersion()) { + case OnapCommandSnmpConstants.SNMP_VERSION_V1: + target.setVersion(SnmpConstants.version1); + break; + + case OnapCommandSnmpConstants.SNMP_VERSION_V2C: + target.setVersion(SnmpConstants.version2c); + break; + + default: + break; + } + return target; + } + + @Override + protected void run() throws OnapCommandException { + try { + + // set JVM constant to avoid delay by snmp4j + System.setProperty("java.security.egd", "file:data/./urandom"); + + DefaultUdpTransportMapping defaultUdpTransportMapping = new DefaultUdpTransportMapping(); + defaultUdpTransportMapping.listen(); + Snmp snmp = new Snmp(defaultUdpTransportMapping); + + List<String> oids = new ArrayList<>(); + for (Map<String, String> map: resultMap) { + oids.addAll(map.values()); + } + + String[] oidStrArr = oids.toArray(new String[oids.size()]); + + switch (this.command) { + + case OnapCommandSnmpConstants.SNMP_CMD_GET: + ResponseEvent responseEvent = snmp.send(getPDU(PDU.GET, oidStrArr), getTarget(), null); + if ( responseEvent != null || responseEvent.getResponse().getErrorStatus() == PDU.noError) { + Vector<? extends VariableBinding> variableBindings = responseEvent.getResponse().getVariableBindings(); + variableBindings.stream().forEach(varBinding -> { //NOSONAR + String key = getKeyForValue(varBinding.getOid().toString()); + if (key != null) { + this.getResult().getRecordsMap().get(key).getValues().add( + varBinding.getVariable().toString()); + } + }); + } else { + throw new OnapSnmpErrorResponse("Error response from SNMP agent", + responseEvent.getResponse().getErrorStatus()); + } + break; + + default: + break; + } + snmp.close(); + } catch (IOException ex) { + throw new OnapSnmpErrorResponse(ex); + } + } + + private String getKeyForValue(String value) { + Optional<Map<String, String>> mapOptional = resultMap.stream().filter(map -> map.values().contains(value)).findFirst(); //NOSONAR + if (!mapOptional.isPresent()) { + return null; + } + return mapOptional.get().keySet().iterator().next(); + } + + @Override + protected List<String> initializeProfileSchema(Map<String, ?> schemaMap, boolean validate) throws OnapCommandException { + return OnapCommandSchemaSnmpLoader.parseSnmpSchema(this, schemaMap, validate); + } + + public String getSnmpVersion() { + return version; + } + + public void setSnmpVersion(String version) { + this.version = version; + } + + public String getCommand() { + return command; + } + + public void setCommand(String command) { + this.command = command; + } + + + public List<Map<String, String>> getResultMap() { + return resultMap; + } + + public void setResultMap(List<Map<String, String>> resultMap) { + this.resultMap = resultMap; + } + +} diff --git a/profiles/snmp/src/main/java/org/onap/cli/fw/snmp/conf/OnapCommandSnmpConstants.java b/profiles/snmp/src/main/java/org/onap/cli/fw/snmp/conf/OnapCommandSnmpConstants.java new file mode 100644 index 00000000..2ebfd990 --- /dev/null +++ b/profiles/snmp/src/main/java/org/onap/cli/fw/snmp/conf/OnapCommandSnmpConstants.java @@ -0,0 +1,43 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * 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.onap.cli.fw.snmp.conf; + +/** + * OnapCommandHttpConstants. + * + */ +public class OnapCommandSnmpConstants { + public static final String SNMP_SCHEMA_PROFILE = "snmp"; + public static final String SNMP = "snmp"; + public static final String SNMP_VERSION = "version"; + public static final String SNMP_RESULTMAP = "result_map"; + public static final String SNMP_COMMAND = "command"; + public static final String SNMP_AGENT = "agent"; + public static final String SNMP_COMMNUNITY_STRING = "public"; + public static final String SNMP_CMD_GET = "get"; + public static final String SNMP_CMD_SET = "set"; + public static final String DEFAULT_PARAMETER_SNMP_FILE_NAME = "default_input_parameters_snmp.yaml"; + public static final String SNMP_METHODS = "cli.schema.snmp_methods"; + public static final String SNMP_REQUEST_PARAMS = "cli.schema.snmp_request_params"; + public static final String SNMP_REQUEST_MANDATORY_PARAMS = "cli.schema.snmp_request_mandatory_params"; + public static final int RETRY_COUNT = 2; + public static final int TIMEOUT = 1500; + public static final String SNMP_VERSION_V1 = "v1"; + public static final String SNMP_VERSION_V2C = "v2c"; +} + + diff --git a/profiles/snmp/src/main/java/org/onap/cli/fw/snmp/exception/OnapSnmpErrorResponse.java b/profiles/snmp/src/main/java/org/onap/cli/fw/snmp/exception/OnapSnmpErrorResponse.java new file mode 100644 index 00000000..87b9241f --- /dev/null +++ b/profiles/snmp/src/main/java/org/onap/cli/fw/snmp/exception/OnapSnmpErrorResponse.java @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * 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.onap.cli.fw.snmp.exception; + +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.error.OnapCommandExecutionFailed; + +/** + * Command execution failed. + * + */ +public class OnapSnmpErrorResponse extends OnapCommandExecutionFailed { + private static final long serialVersionUID = 488775545433833345L; + + private static final String ERROR_CODE = "0x1001"; + + public OnapSnmpErrorResponse(String error, long responseStatus) { + super(ERROR_CODE, error, responseStatus); + } + + public OnapSnmpErrorResponse(String error) { + super(ERROR_CODE, error); + } + + public OnapSnmpErrorResponse(Throwable throwable) { + super(ERROR_CODE, throwable); + } + + public OnapSnmpErrorResponse(Throwable throwable, long responseStatus) { + super(ERROR_CODE, throwable, responseStatus); + } + +}
\ No newline at end of file diff --git a/profiles/snmp/src/main/java/org/onap/cli/fw/snmp/schema/OnapCommandSchemaSnmpLoader.java b/profiles/snmp/src/main/java/org/onap/cli/fw/snmp/schema/OnapCommandSchemaSnmpLoader.java new file mode 100644 index 00000000..87cde127 --- /dev/null +++ b/profiles/snmp/src/main/java/org/onap/cli/fw/snmp/schema/OnapCommandSchemaSnmpLoader.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * 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.onap.cli.fw.snmp.schema; + +import org.onap.cli.fw.conf.OnapCommandConfig; +import org.onap.cli.fw.conf.OnapCommandConstants; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.schema.OnapCommandSchemaLoader; +import org.onap.cli.fw.snmp.cmd.OnapSnmpCommand; +import org.onap.cli.fw.snmp.conf.OnapCommandSnmpConstants; +import org.onap.cli.fw.utils.OnapCommandUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class OnapCommandSchemaSnmpLoader { + + private static List<String> validateSnmpSchemaSection(Map<String, Object> values) { + ArrayList<String> errorList = new ArrayList<>(); + + OnapCommandUtils.validateTags(errorList, values, + OnapCommandConfig.getCommaSeparatedList(OnapCommandSnmpConstants.SNMP_REQUEST_PARAMS), + OnapCommandConfig.getCommaSeparatedList(OnapCommandSnmpConstants.SNMP_REQUEST_MANDATORY_PARAMS), + OnapCommandSnmpConstants.SNMP); + return errorList; + } + + public static ArrayList<String> parseSnmpSchema(OnapSnmpCommand cmd, + final Map<String, ?> values, + boolean validate) throws OnapCommandException { + + ArrayList<String> errorList = new ArrayList<>(); + Map<String, ?> valMap = (Map<String, ?>) values.get(OnapCommandSnmpConstants.SNMP); + + if (valMap!=null) { + if (validate) { + errorList.addAll(validateSnmpSchemaSection((Map<String, Object>) valMap)); + } + for (Map.Entry<String, ?> entry : valMap.entrySet()) { + switch (entry.getKey()) { + case OnapCommandSnmpConstants.SNMP_RESULTMAP: + cmd.setResultMap((List<Map<String, String>>) entry.getValue()); + break; + + case OnapCommandSnmpConstants.SNMP_VERSION: + cmd.setSnmpVersion((String) entry.getValue()); + break; + + case OnapCommandSnmpConstants.SNMP_COMMAND: + cmd.setCommand((String) entry.getValue()); + + default: + break; + } + } + } + return errorList; + } +} diff --git a/profiles/snmp/src/main/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand b/profiles/snmp/src/main/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand new file mode 100644 index 00000000..59d23e1a --- /dev/null +++ b/profiles/snmp/src/main/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand @@ -0,0 +1 @@ +org.onap.cli.fw.snmp.cmd.OnapSnmpCommand
\ No newline at end of file diff --git a/profiles/snmp/src/main/resources/open-cli-schema/snmp/default_input_parameters_snmp.yaml b/profiles/snmp/src/main/resources/open-cli-schema/snmp/default_input_parameters_snmp.yaml new file mode 100644 index 00000000..ecce7130 --- /dev/null +++ b/profiles/snmp/src/main/resources/open-cli-schema/snmp/default_input_parameters_snmp.yaml @@ -0,0 +1,10 @@ +open_cli_schema_version: 1.0 + +parameters: + - name: agent + description: agent address (eg. "udp:127.0.0.1/161") + type: string + short_option: x + long_option: agent + is_optional: false + is_default_param: true
\ No newline at end of file diff --git a/profiles/snmp/src/main/resources/open-cli-snmp.properties b/profiles/snmp/src/main/resources/open-cli-snmp.properties new file mode 100644 index 00000000..e8ee5af5 --- /dev/null +++ b/profiles/snmp/src/main/resources/open-cli-snmp.properties @@ -0,0 +1,9 @@ +cli.ignore_auth=false + +#schema validation +#snmp + +cli.schema.snmp_request_params=command,version,result_map +cli.schema.snmp_request_mandatory_params=command,version + +cli.schema.snmp_methods=get
\ No newline at end of file diff --git a/profiles/snmp/src/test/java/org/onap/cli/fw/snmp/cmd/OnapSnmpCommandTest.java b/profiles/snmp/src/test/java/org/onap/cli/fw/snmp/cmd/OnapSnmpCommandTest.java new file mode 100644 index 00000000..00c985d5 --- /dev/null +++ b/profiles/snmp/src/test/java/org/onap/cli/fw/snmp/cmd/OnapSnmpCommandTest.java @@ -0,0 +1,97 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * 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.onap.cli.fw.snmp.cmd; + +import mockit.Mock; +import mockit.MockUp; +import org.junit.*; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.error.OnapCommandInvalidParameterValue; +import org.onap.cli.fw.input.OnapCommandParameter; +import org.onap.cli.fw.input.OnapCommandParameterType; +import org.onap.cli.fw.output.OnapCommandResult; +import org.onap.cli.fw.output.OnapCommandResultAttribute; +import org.snmp4j.PDU; +import org.snmp4j.Snmp; +import org.snmp4j.Target; +import org.snmp4j.TransportMapping; +import org.snmp4j.event.ResponseEvent; +import org.snmp4j.smi.OID; +import org.snmp4j.smi.OctetString; +import org.snmp4j.smi.VariableBinding; + +import java.io.IOException; +import java.util.*; + +import static org.junit.Assert.*; + +public class OnapSnmpCommandTest { + + @Test + public void testSnmpGetCommand() throws OnapCommandException { + + new MockUp<Snmp>() { + @Mock + public ResponseEvent send(PDU pdu, Target target, TransportMapping transport) throws IOException { + PDU pdu1 = new PDU(); + pdu1.setType(-94); + VariableBinding variableBinding = new VariableBinding(new OID("1.3.6.1.2.1.1.1.0")); + variableBinding.setVariable(new OctetString(new byte[] {'s', 'n', 'm', 'p'})); + + pdu1.setVariableBindings(Arrays.asList(variableBinding)); + return new ResponseEvent(new Object(), null, pdu, pdu1, null); + } + }; + + OnapSnmpCommand snmpCmd = new OnapSnmpCommand(); + + HashMap<String, String> resultMapEntry = new HashMap<>(); + resultMapEntry.put("system-desc", "1.3.6.1.2.1.1.1.0"); + + List<Map<String, String>> resultMap = Arrays.asList(resultMapEntry); + snmpCmd.setResultMap(resultMap); + snmpCmd.setSnmpVersion("1"); + snmpCmd.setCommand("get"); + + OnapCommandParameter onapCommandParameter = new OnapCommandParameter(); + onapCommandParameter.setName("agent"); + onapCommandParameter.setParameterType(OnapCommandParameterType.STRING); + onapCommandParameter.setShortOption("x"); + onapCommandParameter.setOptional(false); + onapCommandParameter.setLongOption("agent"); + onapCommandParameter.setValue("udp:0.0.0.0/161"); + + Set<OnapCommandParameter> parameters = new HashSet<>(); + parameters.add(onapCommandParameter); + snmpCmd.setParameters(parameters); + + OnapCommandResultAttribute onapCommandResultAttribute = new OnapCommandResultAttribute(); + onapCommandResultAttribute.setValues(new ArrayList<>()); + onapCommandResultAttribute.setName("system-desc"); + + + OnapCommandResult onapCommandResult = new OnapCommandResult(); + onapCommandResult.setRecords(Arrays.asList(onapCommandResultAttribute)); + snmpCmd.setResult(onapCommandResult); + + snmpCmd.run(); + + OnapCommandResult result = snmpCmd.getResult(); + assertEquals("snmp", result.getRecordsMap().get("system-desc") + .getValues().get(0)); + } +}
\ No newline at end of file diff --git a/profiles/snmp/src/test/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand b/profiles/snmp/src/test/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand new file mode 100644 index 00000000..59d23e1a --- /dev/null +++ b/profiles/snmp/src/test/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand @@ -0,0 +1 @@ +org.onap.cli.fw.snmp.cmd.OnapSnmpCommand
\ No newline at end of file diff --git a/profiles/snmp/src/test/resources/open-cli.properties b/profiles/snmp/src/test/resources/open-cli.properties new file mode 100644 index 00000000..ed406331 --- /dev/null +++ b/profiles/snmp/src/test/resources/open-cli.properties @@ -0,0 +1,31 @@ +cli.product_name=open-cli +cli.version=1.0 + +cli.discover_always=false + +#schema validation +cli.schema.top_level_params_list=open_cli_schema_version,name,description,parameters,results,http,info +cli.schema.top_level_mandatory_list=open_cli_schema_version + +cli.schema.info_params_list=product,service,type,author,ignore +cli.schema.info_params_mandatory_list=product,service + +cli.schema.input_params_list=name,description,type,short_option,long_option, is_optional,default_value,is_secured,is_include +cli.schema.input_params_mandatory_list=name,description,type + +cli.schema.result_params_list=name,description,scope,type,is_secured, default_value +cli.schema.result_params_mandatory_list=name, description, type, scope + +cli.schema.boolean_values=true,false +cli.command.type=cmd,auth,catalog + +# moco properties +cli.sample.gen.enable=false +cli.sample.gen.target=. + +# mrkanag Move this to db, once exteranl command registration is supported in place of discovery +cli.schema.type.supported=snmp + +#other properties to load (it should be hanled when plugins are made as externally register-able +#when command plugin management support is enabled in oclip +cli.plugins-prps=,open-cli-snmp.properties
\ No newline at end of file |