View Javadoc

1   /**
2    * Copyright (c) 2011, University of Konstanz, Distributed Systems Group All
3    * rights reserved. Redistribution and use in source and binary forms, with or
4    * without modification, are permitted provided that the following conditions
5    * are met: * Redistributions of source code must retain the above copyright
6    * notice, this list of conditions and the following disclaimer. *
7    * Redistributions in binary form must reproduce the above copyright notice,
8    * this list of conditions and the following disclaimer in the documentation
9    * and/or other materials provided with the distribution. * Neither the name of
10   * the University of Konstanz nor the names of its contributors may be used to
11   * endorse or promote products derived from this software without specific prior
12   * written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
13   * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
14   * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
15   * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE
16   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
18   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
19   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
20   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
22   * POSSIBILITY OF SUCH DAMAGE.
23   */
24  
25  package org.treetank.jscsi;
26  
27  import java.io.BufferedReader;
28  import java.io.File;
29  import java.io.InputStreamReader;
30  import java.net.InetAddress;
31  import java.net.NetworkInterface;
32  import java.util.ArrayList;
33  import java.util.Enumeration;
34  import java.util.HashMap;
35  import java.util.List;
36  import java.util.Map;
37  import java.util.Properties;
38  
39  import org.jscsi.target.TargetServer;
40  import org.treetank.access.Storage;
41  import org.treetank.access.conf.ModuleSetter;
42  import org.treetank.access.conf.ResourceConfiguration;
43  import org.treetank.access.conf.ResourceConfiguration.IResourceConfigurationFactory;
44  import org.treetank.access.conf.SessionConfiguration;
45  import org.treetank.access.conf.StandardSettings;
46  import org.treetank.access.conf.StorageConfiguration;
47  import org.treetank.api.ISession;
48  import org.treetank.api.IStorage;
49  import org.treetank.data.BlockDataElementFactory;
50  import org.treetank.data.ISCSIMetaPageFactory;
51  import org.treetank.io.IBackend;
52  import org.treetank.io.IOUtils;
53  import org.treetank.io.berkeley.BerkeleyStorage;
54  import org.treetank.io.jclouds.JCloudsStorage;
55  import org.treetank.revisioning.IRevisioning;
56  import org.treetank.revisioning.SlidingSnapshot;
57  
58  import com.google.common.io.Files;
59  import com.google.inject.Guice;
60  import com.google.inject.Injector;
61  
62  /**
63   * Start a target server that uses a treetank storage as storage device.
64   * 
65   * @author Andreas Rain
66   * 
67   */
68  public class TreetankTargetServer {
69  
70      /**
71       * Starts the jSCSI target.
72       * 
73       * Argument one has to be an empty (or already created) storage folder!
74       * Argument to can be additionally added if you don't want the default target configuration.
75       * It has to be conform with the default target configuration schema file, which you can find
76       * in the resources of the target.
77       * 
78       * @param args
79       *            storagePath=<PathToStorage> | If using an existing storage, make sure not to pass a backend
80       *            implementation or revisioning implementation again.
81       *            targetConfiguration=<PathToTargetConfigurationFile> | This usually is an .xml-File that
82       *            corresponds to the one that can be found in the sources.
83       *            backendImplementation=<FullyQualifiedPath> | E.g.: org.treetank.io.combined.CombinedStorage
84       *            (which also is default)
85       *            revisioningImplementation=<FullyQualifiedPath> | E.g.:
86       *            org.treetank.revisioning.SlidingSnapshot (which also is default)
87       * 
88       * @throws Exception
89       */
90      @SuppressWarnings("unchecked")
91      public static void main(String[] args) throws Exception {
92          Map<String, String> argsMap = new HashMap<>();
93  
94          for (int i = 0; i < args.length; i++) {
95              if (args[i].equals("help")) {
96                  printHelp();
97              }
98  
99              System.out.print("Argument: " + args[i]);
100             String[] splitArg = args[i].split("=");
101 
102             if (splitArg.length == 2) {
103                 System.out.println(" is valid");
104                 argsMap.put(splitArg[0], splitArg[1]);
105             } else {
106                 System.out.println(" is invalid");
107             }
108         }
109 
110         StorageConfiguration config;
111         File configFile;
112         Class<? extends IBackend> backendClass;
113         Class<? extends IRevisioning> revisioningClass;
114 
115         System.out.println("\nThis system provides more than one IP Address to advertise.\n");
116 
117         Enumeration<NetworkInterface> interfaceEnum = NetworkInterface.getNetworkInterfaces();
118         NetworkInterface i;
119         int addressCounter = 0;
120         List<InetAddress> addresses = new ArrayList<InetAddress>();
121         while (interfaceEnum.hasMoreElements()) {
122             i = interfaceEnum.nextElement();
123             Enumeration<InetAddress> addressEnum = i.getInetAddresses();
124             InetAddress address;
125 
126             while (addressEnum.hasMoreElements()) {
127                 address = addressEnum.nextElement();
128                 System.out.println("[" + addressCounter + "] " + address.getHostAddress());
129                 addresses.add(address);
130                 addressCounter++;
131             }
132         }
133 
134         /*
135          * Getting the desired address from the command line.
136          * You can't automatically make sure to always use the correct
137          * host address.
138          */
139         System.out.print("\nWhich one should be used?\nType in the number: ");
140         Integer chosenIndex = null;
141 
142         while (chosenIndex == null) {
143             BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
144             String line = br.readLine();
145             try {
146                 chosenIndex = Integer.parseInt(line);
147             } catch (NumberFormatException nfe) {
148                 chosenIndex = null;
149             }
150         }
151 
152         String targetAddress = addresses.get(chosenIndex).getHostAddress();
153         System.out.println("Using ip address " + addresses.get(chosenIndex).getHostAddress());
154 
155         if (argsMap.get("storagePath") != null) {
156             File file = new File(argsMap.get("storagePath"));
157             config = new StorageConfiguration(file);
158         } else {
159 //            String file = Files.createTempDir().getAbsolutePath();
160         	String file = "/tmp/tttarget";
161             config =
162                 new StorageConfiguration(new File(new StringBuilder(file).append(File.separator)
163                     .append("tnk").append(File.separator).append("path1").toString()));
164         }
165 
166         if (argsMap.get("targetConfiguration") != null) {
167             configFile = new File(argsMap.get("targetConfiguration"));
168         } else {
169             configFile = TreetankConfiguration.CONFIGURATION_CONFIG_FILE;
170         }
171 
172         if (argsMap.get("backendImplementation") != null) {
173             backendClass = (Class<? extends IBackend>)Class.forName(argsMap.get("backendImplementation"));
174         } else {
175             backendClass = JCloudsStorage.class;
176         }
177 
178         if (argsMap.get("revisioningImplementation") != null) {
179             revisioningClass =
180                 (Class<? extends IRevisioning>)Class.forName(argsMap.get("revisioningImplementation"));
181         } else {
182             revisioningClass = SlidingSnapshot.class;
183         }
184         
185         IOUtils.recursiveDelete(config.mFile);
186         Storage.createStorage(config);
187 
188         final String resourceName="bench53473ResourcegraveISCSI9284";
189         
190         // Guice Stuff for building the module
191         final Injector injector =
192             Guice.createInjector(new ModuleSetter().setDataFacClass(BlockDataElementFactory.class).setMetaFacClass(
193                 ISCSIMetaPageFactory.class).setBackendClass(backendClass).setRevisioningClass(
194                 revisioningClass).createModule());
195         final IResourceConfigurationFactory resFac =
196             injector.getInstance(IResourceConfigurationFactory.class);
197         final Properties props = StandardSettings.getProps(config.mFile.getAbsolutePath(), resourceName);
198         final ResourceConfiguration resConf = resFac.create(props);
199 
200         final IStorage db = Storage.openStorage(config.mFile);
201         db.createResource(resConf);
202         final ISession session = db.getSession(new SessionConfiguration(resourceName, StandardSettings.KEY));
203 
204         TargetServer target =
205             new TargetServer(TreetankConfiguration.create(TreetankConfiguration.CONFIGURATION_SCHEMA_FILE,
206                 configFile, session, targetAddress));
207 
208         target.call();
209     }
210 
211     private static void printHelp() {
212         StringBuilder helpStringBuilder = new StringBuilder();
213         helpStringBuilder
214             .append("Treetank Target Server Help")
215             .append("\n__________________________________\n\n")
216             .append("Usage: java jar TreetankTargetServer-<version>.jar")
217             .append("\n\n")
218             .append("Arguments:")
219             .append("\n\n")
220             .append("\t")
221             .append("storagePath=<PathToStorage>")
222             .append("\t\t\t\t| ")
223             .append(
224                 "If using an existing storage, make sure not to pass a backend implementation or revisioning implementation again.")
225             .append("\n")
226             .append("\t")
227             .append("targetConfiguration=<PathToTargetConfigurationFile>")
228             .append("\t| ")
229             .append(
230                 "This usually is an .xml-File that corresponds to the one that can be found in the sources.")
231             .append("\n")
232             .append("\t")
233             .append("backendImplementation=<FullyQualifiedPath>")
234             .append("\t\t| ")
235             .append("E.g.: org.treetank.io.combined.CombinedStorage (which also is default)")
236             .append("\n")
237             .append("\t")
238             .append("revisioningImplementation=<FullyQualifiedPath>")
239             .append("\t\t| ")
240             .append("E.g.: org.treetank.revisioning.SlidingSnapshot (which also is default)")
241             .append("\n\n")
242             .append(
243                 "You can leave out all arguments to test the system, in which case default settings are used.");
244 
245         System.out.println(helpStringBuilder.toString());
246 
247         System.exit(0);
248     }
249 }