Pamela Dragosh | 5ed4e85 | 2017-09-22 12:26:16 -0400 | [diff] [blame] | 1 | .. This work is licensed under a Creative Commons Attribution 4.0 International License. |
| 2 | .. http://creativecommons.org/licenses/by/4.0 |
| 3 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 4 | Standalone Quick Start Installation |
| 5 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
Saryu Shah | ba1936f | 2017-10-10 22:20:01 +0000 | [diff] [blame] | 6 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 7 | .. contents:: |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 8 | :depth: 2 |
Saryu Shah | ba1936f | 2017-10-10 22:20:01 +0000 | [diff] [blame] | 9 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 10 | The installation of ONAP Policy is **automated** by design and can be done via Docker as a standalone system. |
Saryu Shah | ba1936f | 2017-10-10 22:20:01 +0000 | [diff] [blame] | 11 | Various tools, including healthcheck, logs, and Swagger can be used to ensure proper operation. |
| 12 | |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 13 | This article explains how to build the ONAP Policy Framework and get it running in Docker as a standalone system. |
| 14 | This article assumes that: |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 15 | |
| 16 | * You are using a *\*nix* operating system such as linux or macOS. |
| 17 | * You are using a directory called *git* off your home directory *(~/git)* for your git repositories |
| 18 | * Your local maven repository is in the location *~/.m2/repository* |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 19 | * You have added settings to access the ONAP Nexus to your M2 configuration, see `Maven Settings Example <https://wiki.onap.org/display/DW/Setting+Up+Your+Development+Environment>`_ (bottom of the linked page) |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 20 | |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 21 | The procedure documented in this article has been verified to work on a MacBook laptop running macOS Sierra Version 10.12.6 and a HP Z600 desktop running Ubuntu 16.04.3 LTS. |
| 22 | |
| 23 | Cloning the ONAP repositories |
| 24 | ----------------------------- |
| 25 | |
| 26 | Run a script such as the script below to clone the required modules from the `ONAP git repository <https://gerrit.onap.org/r/#/admin/projects/?filter=policy>`_. This script clones the ONAP policy code and also clones some modules that ONAP Policy is dependent on. |
| 27 | |
| 28 | ONAP Policy requires all the *policy* modules from the ONAP repository. It also requires the ONAP Parent *oparent* module and the ONAP ECOMP SDK *ecompsdkos* module. |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 29 | |
| 30 | |
Saryu Shah | f45cebe | 2017-10-13 14:17:11 +0000 | [diff] [blame] | 31 | .. code-block:: bash |
| 32 | :caption: Typical ONAP Policy Framework Clone Script |
| 33 | :linenos: |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 34 | |
| 35 | #!/usr/bin/env bash |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 36 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 37 | ## script name for output |
| 38 | MOD_SCRIPT_NAME=`basename $0` |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 39 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 40 | ## the ONAP clone directory, defaults to "onap" |
| 41 | clone_dir="onap" |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 42 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 43 | ## the ONAP repos to clone |
| 44 | onap_repos="\ |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 45 | policy/api \ |
| 46 | policy/common \ |
| 47 | policy/docker \ |
| 48 | policy/drools-applications \ |
| 49 | policy/drools-pdp \ |
| 50 | policy/engine \ |
| 51 | policy/gui \ |
| 52 | policy/pap \ |
| 53 | policy/pdp" |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 54 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 55 | ## |
| 56 | ## Help screen and exit condition (i.e. too few arguments) |
| 57 | ## |
| 58 | Help() |
| 59 | { |
| 60 | echo "" |
| 61 | echo "$MOD_SCRIPT_NAME - clones all required ONAP git repositories" |
| 62 | echo "" |
| 63 | echo " Usage: $MOD_SCRIPT_NAME [-options]" |
| 64 | echo "" |
| 65 | echo " Options" |
| 66 | echo " -d - the ONAP clone directory, defaults to '.'" |
| 67 | echo " -h - this help screen" |
| 68 | echo "" |
| 69 | exit 255; |
| 70 | } |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 71 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 72 | ## |
| 73 | ## read command line |
| 74 | ## |
| 75 | while [ $# -gt 0 ] |
| 76 | do |
| 77 | case $1 in |
| 78 | #-d ONAP clone directory |
| 79 | -d) |
| 80 | shift |
| 81 | if [ -z "$1" ]; then |
| 82 | echo "$MOD_SCRIPT_NAME: no clone directory" |
| 83 | exit 1 |
| 84 | fi |
| 85 | clone_dir=$1 |
| 86 | shift |
| 87 | ;; |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 88 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 89 | #-h prints help and exists |
| 90 | -h) |
| 91 | Help;exit 0;; |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 92 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 93 | *) echo "$MOD_SCRIPT_NAME: undefined CLI option - $1"; exit 255;; |
| 94 | esac |
| 95 | done |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 96 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 97 | if [ -f "$clone_dir" ]; then |
| 98 | echo "$MOD_SCRIPT_NAME: requested clone directory '$clone_dir' exists as file" |
| 99 | exit 2 |
| 100 | fi |
| 101 | if [ -d "$clone_dir" ]; then |
| 102 | echo "$MOD_SCRIPT_NAME: requested clone directory '$clone_dir' exists as directory" |
| 103 | exit 2 |
| 104 | fi |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 105 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 106 | mkdir $clone_dir |
| 107 | if [ $? != 0 ] |
| 108 | then |
| 109 | echo cannot clone ONAP repositories, could not create directory '"'$clone_dir'"' |
| 110 | exit 3 |
| 111 | fi |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 112 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 113 | for repo in $onap_repos |
| 114 | do |
| 115 | repoDir=`dirname "$repo"` |
| 116 | repoName=`basename "$repo"` |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 117 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 118 | if [ ! -z $dirName ] |
| 119 | then |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 120 | mkdir "$clone_dir/$repoDir" |
| 121 | if [ $? != 0 ] |
| 122 | then |
| 123 | echo cannot clone ONAP repositories, could not create directory '"'$clone_dir/repoDir'"' |
| 124 | exit 4 |
| 125 | fi |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 126 | fi |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 127 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 128 | git clone https://gerrit.onap.org/r/${repo} $clone_dir/$repo |
| 129 | done |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 130 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 131 | echo ONAP has been cloned into '"'$clone_dir'"' |
| 132 | |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 133 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 134 | Execution of the script above results in the following directory hierarchy in your *~/git* directory: |
| 135 | |
Saryu Shah | 3eddd58 | 2017-10-12 22:03:55 +0000 | [diff] [blame] | 136 | * ~/git/onap |
Saryu Shah | 3eddd58 | 2017-10-12 22:03:55 +0000 | [diff] [blame] | 137 | * ~/git/onap/policy |
| 138 | * ~/git/onap/policy/api |
| 139 | * ~/git/onap/policy/common |
| 140 | * ~/git/onap/policy/docker |
| 141 | * ~/git/onap/policy/drools-applications |
| 142 | * ~/git/onap/policy/drools-pdp |
| 143 | * ~/git/onap/policy/engine |
| 144 | * ~/git/onap/policy/gui |
| 145 | * ~/git/onap/policy/pap |
| 146 | * ~/git/onap/policy/pdp |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 147 | |
| 148 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 149 | Building ONAP |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 150 | ------------- |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 151 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 152 | **Step 1:** Optionally, for a completely clean build, remove the ONAP built modules from your local repository. |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 153 | |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 154 | .. code-block:: bash |
| 155 | |
| 156 | rm -fr ~/.m2/repository/org/onap |
| 157 | rm -fr ~/.m2/repository/org/openecomp |
| 158 | rm -fr ~/.m2/repisotory/com/att |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 159 | |
Saryu Shah | f45cebe | 2017-10-13 14:17:11 +0000 | [diff] [blame] | 160 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 161 | **Step 2:** A pom such as the one below can be used to build the ONAP Policy Framework modules. Create the *pom.xml* file in the directory *~/git/onap/policy*. |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 162 | |
Saryu Shah | f45cebe | 2017-10-13 14:17:11 +0000 | [diff] [blame] | 163 | .. code-block:: xml |
| 164 | :caption: Typical pom.xml to build the ONAP Policy Framework |
| 165 | :linenos: |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 166 | |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 167 | <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"> |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 168 | <modelVersion>4.0.0</modelVersion> |
| 169 | <groupId>org.onap</groupId> |
| 170 | <artifactId>onap-policy</artifactId> |
| 171 | <version>1.0.0-SNAPSHOT</version> |
| 172 | <packaging>pom</packaging> |
| 173 | <name>${project.artifactId}</name> |
| 174 | <inceptionYear>2017</inceptionYear> |
| 175 | <organization> |
| 176 | <name>ONAP</name> |
| 177 | </organization> |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 178 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 179 | <modules> |
| 180 | <module>common</module> |
| 181 | <module>engine</module> |
| 182 | <module>pdp</module> |
| 183 | <module>pap</module> |
| 184 | <module>drools-pdp</module> |
| 185 | <module>drools-applications</module> |
| 186 | <module>api</module> |
| 187 | <module>gui</module> |
| 188 | <module>docker</module> |
| 189 | </modules> |
| 190 | </project> |
| 191 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 192 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 193 | **Step 3:** You can now build the ONAP framework |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 194 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 195 | .. code-block:: bash |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 196 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 197 | cd ~/git/onap |
| 198 | mvn clean install |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 199 | |
| 200 | |
| 201 | Building the ONAP Policy Framework Docker Images |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 202 | ------------------------------------------------ |
| 203 | The instructions here are based on the instructions in the file *~/git/onap/policy/docker/README.md*. |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 204 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 205 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 206 | **Step 1:** Build the policy engine docker image: |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 207 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 208 | .. code-block:: bash |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 209 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 210 | cd ~/git/onap/policy/engine/packages/docker/target |
| 211 | docker build -t onap/policy-pe policy-pe |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 212 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 213 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 214 | **Step 2:** Build the Drools PDP docker image: |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 215 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 216 | .. code-block:: bash |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 217 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 218 | cd ~/git/onap/policy/drools-pdp/packages/docker/target |
| 219 | docker build -t onap/policy-drools policy-drools |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 220 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 221 | |
| 222 | Starting the ONAP Policy Framework Docker Images |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 223 | ------------------------------------------------ |
| 224 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 225 | In order to run the containers, you can use *docker-compose*. This uses the *docker-compose.yml* yaml file to bring up the ONAP Policy Framework. |
| 226 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 227 | **Step 1:** Make the file config/drools/drools-tweaks.sh executable. |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 228 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 229 | .. code-block:: bash |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 230 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 231 | chmod +x config/drools/drools-tweaks.sh |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 232 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 233 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 234 | **Step 2:** Set the IP address to use to be an IP address of a suitable interface on your machine. Save the IP address into the file *config/pe/ip_addr.txt*. |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 235 | |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 236 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 237 | **Step 3:** Set the environment variable *MTU* to be a suitable MTU size for the application. |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 238 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 239 | .. code-block:: bash |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 240 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 241 | export MTU=9126 |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 242 | |
| 243 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 244 | **Step 4:** Determine if you want policies pre-loaded or not. By default, all the configuration and operational policies will be pre-loaded by the docker compose script. If you do not wish for that to happen, then export this variable: |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 245 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 246 | .. code-block:: bash |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 247 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 248 | export PRELOAD_POLICIES=false |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 249 | |
| 250 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 251 | **Step 5:** Run the system using *docker-compose*. Note that on some systems you may have to run the *docker-compose* command as root or using *sudo*. Note that this command takes a number of minutes to execute on a laptop or desktop computer. |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 252 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 253 | .. code-block:: bash |
Saryu Shah | 5c43749 | 2018-03-26 21:50:41 +0000 | [diff] [blame] | 254 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 255 | docker-compose up |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 256 | |
| 257 | |
Saryu Shah | b6209af | 2017-10-11 20:12:38 +0000 | [diff] [blame] | 258 | **You now have a full standalone ONAP Policy framework up and running!** |
| 259 | |
| 260 | |
Saryu Shah | b0c7e3b | 2018-05-01 01:12:23 +0000 | [diff] [blame^] | 261 | Installation of Controllers and Policies |
| 262 | ---------------------------------------- |
| 263 | |
| 264 | You may now install a controller and policies on the ONAP Policy Framework. Follow either of the HowTos below to install either the Amsterdam or Beijing controller and policies. |
| 265 | |
| 266 | * `Installation of Amsterdam Controller and vCPE Policy <installAmsterController.html>`_ |
| 267 | * `Installation of Beijing Controller and Policies <installBeijingController.html>`_ |
| 268 | |
| 269 | |
| 270 | |
Saryu Shah | ba1936f | 2017-10-10 22:20:01 +0000 | [diff] [blame] | 271 | .. _Standalone Quick Start : https://wiki.onap.org/display/DW/ONAP+Policy+Framework%3A+Standalone+Quick+Start |
Pamela Dragosh | 5ed4e85 | 2017-09-22 12:26:16 -0400 | [diff] [blame] | 272 | |
| 273 | |
Saryu Shah | 3198d6d | 2017-11-07 21:40:27 +0000 | [diff] [blame] | 274 | |
| 275 | End of Document |
| 276 | |