Touch-ups to patchpanel app, including adding to Buck build.
Change-Id: I212a575d50f3a38dea83b9ebe0c004b6267b0cbf
Showing
10 changed files
with
62 additions
and
173 deletions
apps/patchpanel/BUCK
0 → 100644
| 1 | +COMPILE_DEPS = [ | ||
| 2 | + '//lib:CORE_DEPS', | ||
| 3 | + '//lib:org.apache.karaf.shell.console', | ||
| 4 | + '//cli:onos-cli', | ||
| 5 | +] | ||
| 6 | + | ||
| 7 | +osgi_jar ( | ||
| 8 | + deps = COMPILE_DEPS, | ||
| 9 | +) | ||
| 10 | + | ||
| 11 | +onos_app ( | ||
| 12 | + title = 'Patch Panel', | ||
| 13 | + category = 'Traffic Steering', | ||
| 14 | + url = 'http://onosproject.org', | ||
| 15 | + description = 'Creates patches between ports on a switch', | ||
| 16 | +) |
| ... | @@ -14,7 +14,8 @@ | ... | @@ -14,7 +14,8 @@ |
| 14 | ~ See the License for the specific language governing permissions and | 14 | ~ See the License for the specific language governing permissions and |
| 15 | ~ limitations under the License. | 15 | ~ limitations under the License. |
| 16 | --> | 16 | --> |
| 17 | -<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/xsd/maven-4.0.0.xsd"> | 17 | +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| 18 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| 18 | <parent> | 19 | <parent> |
| 19 | <artifactId>onos-apps</artifactId> | 20 | <artifactId>onos-apps</artifactId> |
| 20 | <groupId>org.onosproject</groupId> | 21 | <groupId>org.onosproject</groupId> |
| ... | @@ -22,167 +23,35 @@ | ... | @@ -22,167 +23,35 @@ |
| 22 | </parent> | 23 | </parent> |
| 23 | <modelVersion>4.0.0</modelVersion> | 24 | <modelVersion>4.0.0</modelVersion> |
| 24 | 25 | ||
| 25 | - <groupId>org.onosproject</groupId> | 26 | + <artifactId>patchpanel</artifactId> |
| 26 | - <artifactId>patchPanel</artifactId> | ||
| 27 | - <version>1.0</version> | ||
| 28 | <packaging>bundle</packaging> | 27 | <packaging>bundle</packaging> |
| 29 | 28 | ||
| 30 | - <description>ONOS OSGi bundle archetype</description> | 29 | + <description>ONOS patch panel application</description> |
| 31 | <url>http://onosproject.org</url> | 30 | <url>http://onosproject.org</url> |
| 32 | 31 | ||
| 33 | <properties> | 32 | <properties> |
| 34 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | 33 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
| 35 | - <onos.version>1.7.0-SNAPSHOT</onos.version> | 34 | + <onos.app.name>org.onosproject.patchpanel</onos.app.name> |
| 36 | - <onos.app.name>org.onosproject.patchPanel</onos.app.name> | ||
| 37 | <onos.app.title>Patch Panel</onos.app.title> | 35 | <onos.app.title>Patch Panel</onos.app.title> |
| 38 | - <onos.app.origin>Foo, Inc.</onos.app.origin> | 36 | + <onos.app.origin>ON.Lab</onos.app.origin> |
| 39 | - <onos.app.category>default</onos.app.category> | 37 | + <onos.app.category>Traffic Steering</onos.app.category> |
| 40 | <onos.app.url>http://onosproject.org</onos.app.url> | 38 | <onos.app.url>http://onosproject.org</onos.app.url> |
| 41 | - <onos.app.readme>ONOS OSGi bundle archetype.</onos.app.readme> | 39 | + <onos.app.readme>Creates patches between ports on a switch</onos.app.readme> |
| 42 | - | ||
| 43 | </properties> | 40 | </properties> |
| 44 | 41 | ||
| 45 | <dependencies> | 42 | <dependencies> |
| 46 | - <dependency> | ||
| 47 | - <groupId>org.onosproject</groupId> | ||
| 48 | - <artifactId>onos-api</artifactId> | ||
| 49 | - <version>1.7.0-SNAPSHOT</version> | ||
| 50 | - </dependency> | ||
| 51 | - | ||
| 52 | - <dependency> | ||
| 53 | - <groupId>org.onosproject</groupId> | ||
| 54 | - <artifactId>onlab-misc</artifactId> | ||
| 55 | - <version>1.7.0-SNAPSHOT</version> | ||
| 56 | - </dependency> | ||
| 57 | - | ||
| 58 | - <dependency> | ||
| 59 | - <groupId>org.onosproject</groupId> | ||
| 60 | - <artifactId>onlab-osgi</artifactId> | ||
| 61 | - <version>${onos.version}</version> | ||
| 62 | - </dependency> | ||
| 63 | - | ||
| 64 | - <dependency> | ||
| 65 | - <groupId>junit</groupId> | ||
| 66 | - <artifactId>junit</artifactId> | ||
| 67 | - <version>4.12</version> | ||
| 68 | - <scope>test</scope> | ||
| 69 | - </dependency> | ||
| 70 | - | ||
| 71 | - <dependency> | ||
| 72 | - <groupId>org.onosproject</groupId> | ||
| 73 | - <artifactId>onos-api</artifactId> | ||
| 74 | - <version>${onos.version}</version> | ||
| 75 | - <scope>test</scope> | ||
| 76 | - <classifier>tests</classifier> | ||
| 77 | - </dependency> | ||
| 78 | - | ||
| 79 | - <dependency> | ||
| 80 | - <groupId>org.apache.felix</groupId> | ||
| 81 | - <artifactId>org.apache.felix.scr.annotations</artifactId> | ||
| 82 | - <version>1.9.12</version> | ||
| 83 | - <scope>provided</scope> | ||
| 84 | - </dependency> | ||
| 85 | - | ||
| 86 | - <dependency> | ||
| 87 | - <groupId>org.onosproject</groupId> | ||
| 88 | - <artifactId>onos-incubator-api</artifactId> | ||
| 89 | - <version>1.7.0-SNAPSHOT</version> | ||
| 90 | - </dependency> | ||
| 91 | 43 | ||
| 92 | <dependency> | 44 | <dependency> |
| 93 | <groupId>org.onosproject</groupId> | 45 | <groupId>org.onosproject</groupId> |
| 94 | - <artifactId>onos-core-common</artifactId> | 46 | + <artifactId>onos-cli</artifactId> |
| 95 | - <version>1.7.0-SNAPSHOT</version> | 47 | + <version>${project.version}</version> |
| 96 | - </dependency> | ||
| 97 | - | ||
| 98 | - <dependency> | ||
| 99 | - <groupId>org.onosproject</groupId> | ||
| 100 | - <artifactId>onos-cli</artifactId> | ||
| 101 | - <version>1.7.0-SNAPSHOT</version> | ||
| 102 | - <scope>provided</scope> | ||
| 103 | - </dependency> | ||
| 104 | - | ||
| 105 | - <dependency> | ||
| 106 | - <groupId>org.osgi</groupId> | ||
| 107 | - <artifactId>org.osgi.core</artifactId> | ||
| 108 | - <version>5.0.0</version> | ||
| 109 | - <scope>provided</scope> | ||
| 110 | </dependency> | 48 | </dependency> |
| 111 | 49 | ||
| 112 | <dependency> | 50 | <dependency> |
| 113 | <groupId>org.apache.karaf.shell</groupId> | 51 | <groupId>org.apache.karaf.shell</groupId> |
| 114 | <artifactId>org.apache.karaf.shell.console</artifactId> | 52 | <artifactId>org.apache.karaf.shell.console</artifactId> |
| 115 | - <version>3.0.5</version> | ||
| 116 | - <scope>provided</scope> | ||
| 117 | </dependency> | 53 | </dependency> |
| 118 | 54 | ||
| 119 | </dependencies> | 55 | </dependencies> |
| 120 | 56 | ||
| 121 | - <build> | ||
| 122 | - <plugins> | ||
| 123 | - <plugin> | ||
| 124 | - <groupId>org.apache.felix</groupId> | ||
| 125 | - <artifactId>maven-bundle-plugin</artifactId> | ||
| 126 | - <version>3.0.1</version> | ||
| 127 | - <extensions>true</extensions> | ||
| 128 | - </plugin> | ||
| 129 | - <plugin> | ||
| 130 | - <groupId>org.apache.maven.plugins</groupId> | ||
| 131 | - <artifactId>maven-compiler-plugin</artifactId> | ||
| 132 | - <version>2.5.1</version> | ||
| 133 | - <configuration> | ||
| 134 | - <source>1.8</source> | ||
| 135 | - <target>1.8</target> | ||
| 136 | - </configuration> | ||
| 137 | - </plugin> | ||
| 138 | - <plugin> | ||
| 139 | - <groupId>org.apache.felix</groupId> | ||
| 140 | - <artifactId>maven-scr-plugin</artifactId> | ||
| 141 | - <version>1.21.0</version> | ||
| 142 | - <executions> | ||
| 143 | - <execution> | ||
| 144 | - <id>generate-scr-srcdescriptor</id> | ||
| 145 | - <goals> | ||
| 146 | - <goal>scr</goal> | ||
| 147 | - </goals> | ||
| 148 | - </execution> | ||
| 149 | - </executions> | ||
| 150 | - <configuration> | ||
| 151 | - <supportedProjectTypes> | ||
| 152 | - <supportedProjectType>bundle</supportedProjectType> | ||
| 153 | - <supportedProjectType>war</supportedProjectType> | ||
| 154 | - </supportedProjectTypes> | ||
| 155 | - </configuration> | ||
| 156 | - </plugin> | ||
| 157 | - <plugin> | ||
| 158 | - <groupId>org.onosproject</groupId> | ||
| 159 | - <artifactId>onos-maven-plugin</artifactId> | ||
| 160 | - <version>1.9</version> | ||
| 161 | - <executions> | ||
| 162 | - <execution> | ||
| 163 | - <id>cfg</id> | ||
| 164 | - <phase>generate-resources</phase> | ||
| 165 | - <goals> | ||
| 166 | - <goal>cfg</goal> | ||
| 167 | - </goals> | ||
| 168 | - </execution> | ||
| 169 | - <execution> | ||
| 170 | - <id>swagger</id> | ||
| 171 | - <phase>generate-sources</phase> | ||
| 172 | - <goals> | ||
| 173 | - <goal>swagger</goal> | ||
| 174 | - </goals> | ||
| 175 | - </execution> | ||
| 176 | - <execution> | ||
| 177 | - <id>app</id> | ||
| 178 | - <phase>package</phase> | ||
| 179 | - <goals> | ||
| 180 | - <goal>app</goal> | ||
| 181 | - </goals> | ||
| 182 | - </execution> | ||
| 183 | - </executions> | ||
| 184 | - </plugin> | ||
| 185 | - </plugins> | ||
| 186 | - </build> | ||
| 187 | - | ||
| 188 | </project> | 57 | </project> | ... | ... |
| ... | @@ -28,10 +28,11 @@ import org.onosproject.net.ConnectPoint; | ... | @@ -28,10 +28,11 @@ import org.onosproject.net.ConnectPoint; |
| 28 | import org.onosproject.net.DeviceId; | 28 | import org.onosproject.net.DeviceId; |
| 29 | import org.onosproject.patchpanel.impl.PatchPanelService; | 29 | import org.onosproject.patchpanel.impl.PatchPanelService; |
| 30 | 30 | ||
| 31 | -//name of command and description | 31 | +/** |
| 32 | + * Command for adding a new patch. | ||
| 33 | + */ | ||
| 32 | @Command(scope = "onos", name = "patch", | 34 | @Command(scope = "onos", name = "patch", |
| 33 | description = "Gets the 2 ports of one ConnectPoint that will be patched") | 35 | description = "Gets the 2 ports of one ConnectPoint that will be patched") |
| 34 | - | ||
| 35 | public class PatchPanelCommand extends AbstractShellCommand { | 36 | public class PatchPanelCommand extends AbstractShellCommand { |
| 36 | //the 2 arguments, both connect points | 37 | //the 2 arguments, both connect points |
| 37 | @Argument(index = 0, name = "switch/portNumber", description = "ConnectPoint and first port number", | 38 | @Argument(index = 0, name = "switch/portNumber", description = "ConnectPoint and first port number", | ... | ... |
| ... | @@ -14,15 +14,6 @@ | ... | @@ -14,15 +14,6 @@ |
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -/** | ||
| 18 | - * This class acts as a software patch panel application. | ||
| 19 | - * The user specifies 2 connectpoint on the same device that he/she would like to patch. | ||
| 20 | - * Using a flow rule, the 2 connectpoints are patched. | ||
| 21 | - * | ||
| 22 | - * @author Parvahti Meyyappan | ||
| 23 | - * @version %I%, %G% | ||
| 24 | - */ | ||
| 25 | - | ||
| 26 | package org.onosproject.patchpanel.impl; | 17 | package org.onosproject.patchpanel.impl; |
| 27 | 18 | ||
| 28 | import org.apache.felix.scr.annotations.Component; | 19 | import org.apache.felix.scr.annotations.Component; |
| ... | @@ -31,6 +22,7 @@ import org.apache.felix.scr.annotations.Service; | ... | @@ -31,6 +22,7 @@ import org.apache.felix.scr.annotations.Service; |
| 31 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 22 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
| 32 | import org.apache.felix.scr.annotations.Activate; | 23 | import org.apache.felix.scr.annotations.Activate; |
| 33 | import org.apache.felix.scr.annotations.Deactivate; | 24 | import org.apache.felix.scr.annotations.Deactivate; |
| 25 | +import org.onosproject.cli.net.ConnectPointCompleter; | ||
| 34 | import org.onosproject.core.ApplicationId; | 26 | import org.onosproject.core.ApplicationId; |
| 35 | import org.onosproject.core.CoreService; | 27 | import org.onosproject.core.CoreService; |
| 36 | import org.onosproject.net.PortNumber; | 28 | import org.onosproject.net.PortNumber; |
| ... | @@ -46,11 +38,19 @@ import org.slf4j.LoggerFactory; | ... | @@ -46,11 +38,19 @@ import org.slf4j.LoggerFactory; |
| 46 | import java.util.ArrayList; | 38 | import java.util.ArrayList; |
| 47 | import java.util.List; | 39 | import java.util.List; |
| 48 | 40 | ||
| 49 | - | 41 | +/** |
| 42 | + * This class acts as a software patch panel application. | ||
| 43 | + * The user specifies 2 connectpoint on the same device that he/she would like to patch. | ||
| 44 | + * Using a flow rule, the 2 connectpoints are patched. | ||
| 45 | + */ | ||
| 50 | @Component(immediate = true) | 46 | @Component(immediate = true) |
| 51 | @Service | 47 | @Service |
| 52 | public class PatchPanel implements PatchPanelService { | 48 | public class PatchPanel implements PatchPanelService { |
| 53 | 49 | ||
| 50 | + // OSGI: help bundle plugin discover runtime package dependency. | ||
| 51 | + @SuppressWarnings("unused") | ||
| 52 | + private ConnectPointCompleter connectPointCompleter; | ||
| 53 | + | ||
| 54 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 54 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 55 | protected FlowRuleService flowRuleService; | 55 | protected FlowRuleService flowRuleService; |
| 56 | 56 | ||
| ... | @@ -65,12 +65,8 @@ public class PatchPanel implements PatchPanelService { | ... | @@ -65,12 +65,8 @@ public class PatchPanel implements PatchPanelService { |
| 65 | 65 | ||
| 66 | @Activate | 66 | @Activate |
| 67 | protected void activate() throws NullPointerException { | 67 | protected void activate() throws NullPointerException { |
| 68 | + appId = coreService.registerApplication("org.onosproject.patchpanel"); | ||
| 68 | log.info("Started"); | 69 | log.info("Started"); |
| 69 | - try { | ||
| 70 | - appId = coreService.getAppId("org.onosproject.patchPanel"); | ||
| 71 | - } catch (NullPointerException e) { | ||
| 72 | - throw new NullPointerException("ERROR:App Id is null"); | ||
| 73 | - } | ||
| 74 | } | 70 | } |
| 75 | 71 | ||
| 76 | @Deactivate | 72 | @Deactivate |
| ... | @@ -101,10 +97,18 @@ public class PatchPanel implements PatchPanelService { | ... | @@ -101,10 +97,18 @@ public class PatchPanel implements PatchPanelService { |
| 101 | .withSelector(DefaultTrafficSelector.builder().matchInPort(inPort).build()) | 97 | .withSelector(DefaultTrafficSelector.builder().matchInPort(inPort).build()) |
| 102 | .withTreatment(DefaultTrafficTreatment.builder().setOutput(outPort).build()) | 98 | .withTreatment(DefaultTrafficTreatment.builder().setOutput(outPort).build()) |
| 103 | .withPriority(PacketPriority.REACTIVE.priorityValue()) | 99 | .withPriority(PacketPriority.REACTIVE.priorityValue()) |
| 104 | - .makeTemporary(5) | 100 | + .makePermanent() |
| 101 | + .fromApp(appId).build(); | ||
| 102 | + | ||
| 103 | + FlowRule fr2 = DefaultFlowRule.builder() | ||
| 104 | + .forDevice(cp1.deviceId()) | ||
| 105 | + .withSelector(DefaultTrafficSelector.builder().matchInPort(outPort).build()) | ||
| 106 | + .withTreatment(DefaultTrafficTreatment.builder().setOutput(inPort).build()) | ||
| 107 | + .withPriority(PacketPriority.REACTIVE.priorityValue()) | ||
| 108 | + .makePermanent() | ||
| 105 | .fromApp(appId).build(); | 109 | .fromApp(appId).build(); |
| 106 | 110 | ||
| 107 | - flowRuleService.applyFlowRules(fr); | 111 | + flowRuleService.applyFlowRules(fr, fr2); |
| 108 | 112 | ||
| 109 | } | 113 | } |
| 110 | 114 | ... | ... |
| ... | @@ -18,17 +18,15 @@ package org.onosproject.patchpanel.impl; | ... | @@ -18,17 +18,15 @@ package org.onosproject.patchpanel.impl; |
| 18 | import org.onosproject.net.ConnectPoint; | 18 | import org.onosproject.net.ConnectPoint; |
| 19 | 19 | ||
| 20 | /** | 20 | /** |
| 21 | - * A service for the patch panel application to | 21 | + * A service for the patch panel application to export and use with the cli. |
| 22 | - * export and use with the cli . | ||
| 23 | */ | 22 | */ |
| 24 | public interface PatchPanelService { | 23 | public interface PatchPanelService { |
| 25 | 24 | ||
| 26 | /** | 25 | /** |
| 27 | - * Get the connectPoints that need to be patched. | 26 | + * Adds a new patch between two connect points. |
| 27 | + * | ||
| 28 | * @param cp the first connect point | 28 | * @param cp the first connect point |
| 29 | * @param cp2 the second connect point | 29 | * @param cp2 the second connect point |
| 30 | - * @return void | ||
| 31 | */ | 30 | */ |
| 32 | - public boolean addPatch(ConnectPoint cp, ConnectPoint cp2); | ||
| 33 | - | ||
| 34 | -} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 31 | + boolean addPatch(ConnectPoint cp, ConnectPoint cp2); | ||
| 32 | +} | ... | ... |
| ... | @@ -34,7 +34,7 @@ import java.util.List; | ... | @@ -34,7 +34,7 @@ import java.util.List; |
| 34 | * ONOS UI Custom-View application component for the Patch Panel Application. | 34 | * ONOS UI Custom-View application component for the Patch Panel Application. |
| 35 | */ | 35 | */ |
| 36 | @Component(immediate = true) | 36 | @Component(immediate = true) |
| 37 | -public class AppUiComponent { | 37 | +public class PatchPanelUiComponent { |
| 38 | 38 | ||
| 39 | private static final String VIEW_ID = "sampleCustom"; | 39 | private static final String VIEW_ID = "sampleCustom"; |
| 40 | private static final String VIEW_TEXT = "Patch Panel Application"; | 40 | private static final String VIEW_TEXT = "Patch Panel Application"; |
| ... | @@ -51,7 +51,7 @@ public class AppUiComponent { | ... | @@ -51,7 +51,7 @@ public class AppUiComponent { |
| 51 | 51 | ||
| 52 | // Factory for UI message handlers | 52 | // Factory for UI message handlers |
| 53 | private final UiMessageHandlerFactory messageHandlerFactory = | 53 | private final UiMessageHandlerFactory messageHandlerFactory = |
| 54 | - () -> ImmutableList.of(new AppUiMessageHandler()); | 54 | + () -> ImmutableList.of(new PatchPanelUiMessageHandler()); |
| 55 | 55 | ||
| 56 | // Application UI extension | 56 | // Application UI extension |
| 57 | protected UiExtension extension = | 57 | protected UiExtension extension = | ... | ... |
| ... | @@ -40,7 +40,7 @@ import java.util.List; | ... | @@ -40,7 +40,7 @@ import java.util.List; |
| 40 | * to each event. In this particular implementation the second message | 40 | * to each event. In this particular implementation the second message |
| 41 | * handler creates the patch and the first message handler loads the data | 41 | * handler creates the patch and the first message handler loads the data |
| 42 | */ | 42 | */ |
| 43 | -public class AppUiMessageHandler extends UiMessageHandler { | 43 | +public class PatchPanelUiMessageHandler extends UiMessageHandler { |
| 44 | 44 | ||
| 45 | private static final String SAMPLE_CUSTOM_DATA_REQ = "sampleCustomDataRequest"; | 45 | private static final String SAMPLE_CUSTOM_DATA_REQ = "sampleCustomDataRequest"; |
| 46 | private static final String SAMPLE_CUSTOM_DATA_RESP = "sampleCustomDataResponse"; | 46 | private static final String SAMPLE_CUSTOM_DATA_RESP = "sampleCustomDataResponse"; |
| ... | @@ -136,4 +136,4 @@ public class AppUiMessageHandler extends UiMessageHandler { | ... | @@ -136,4 +136,4 @@ public class AppUiMessageHandler extends UiMessageHandler { |
| 136 | sendMessage(SAMPLE_CUSTOM_DATA_RESP3, sid, payload); | 136 | sendMessage(SAMPLE_CUSTOM_DATA_RESP3, sid, payload); |
| 137 | } | 137 | } |
| 138 | } | 138 | } |
| 139 | -} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 139 | +} | ... | ... |
| ... | @@ -16,6 +16,6 @@ | ... | @@ -16,6 +16,6 @@ |
| 16 | */ | 16 | */ |
| 17 | 17 | ||
| 18 | /** | 18 | /** |
| 19 | - * patch panel-related CLI commands(in implementation folder). | 19 | + * Patch panel-related CLI commands(in implementation folder). |
| 20 | */ | 20 | */ |
| 21 | package org.onosproject.patchpanel.impl; | 21 | package org.onosproject.patchpanel.impl; | ... | ... |
| ... | @@ -150,6 +150,7 @@ ONOS_APPS = [ | ... | @@ -150,6 +150,7 @@ ONOS_APPS = [ |
| 150 | '//apps/cpman/app:onos-apps-cpman-app-oar', | 150 | '//apps/cpman/app:onos-apps-cpman-app-oar', |
| 151 | '//apps/xosclient:onos-apps-xosclient-oar', | 151 | '//apps/xosclient:onos-apps-xosclient-oar', |
| 152 | '//apps/scalablegateway:onos-apps-scalablegateway-oar', | 152 | '//apps/scalablegateway:onos-apps-scalablegateway-oar', |
| 153 | + '//apps/patchpanel:onos-apps-patchpanel-oar', | ||
| 153 | ] | 154 | ] |
| 154 | 155 | ||
| 155 | APP_JARS = [ | 156 | APP_JARS = [ | ... | ... |
-
Please register or login to post a comment