bwLehrpool Masterserver
Manages authentication and sharing of virtual machines between participating institutions
DbImage.java
Go to the documentation of this file.
1 package org.openslx.imagemaster.db.mappers;
2 
3 import java.nio.ByteBuffer;
4 import java.sql.ResultSet;
5 import java.sql.SQLException;
6 import java.util.ArrayList;
7 import java.util.List;
8 
9 import org.apache.logging.log4j.LogManager;
10 import org.apache.logging.log4j.Logger;
11 import org.openslx.bwlp.thrift.iface.ImageDetailsRead;
12 import org.openslx.bwlp.thrift.iface.ImagePermissions;
13 import org.openslx.bwlp.thrift.iface.ImagePublishData;
14 import org.openslx.bwlp.thrift.iface.ImageSummaryRead;
15 import org.openslx.bwlp.thrift.iface.ImageVersionDetails;
16 import org.openslx.bwlp.thrift.iface.InvocationError;
17 import org.openslx.bwlp.thrift.iface.ShareMode;
18 import org.openslx.bwlp.thrift.iface.TInvocationException;
19 import org.openslx.bwlp.thrift.iface.TNotFoundException;
25 import org.openslx.thrifthelper.ImagePublishDataEx;
26 import org.openslx.util.Util;
27 
32 public class DbImage
33 {
34 
35  private static final Logger LOGGER = LogManager.getLogger( DbImage.class );
36 
37  private static final ImagePermissions emptyPermissions = new ImagePermissions();
38 
39  public static ImagePublishDataEx getImageVersion( String imageVersionId ) throws SQLException
40  {
41  try ( MysqlConnection connection = Database.getConnection() ) {
42  MysqlStatement stmt = connection.prepareStatement( "SELECT v.imageversionid, v.imagebaseid, v.createtime, v.filesize, v.filepath,"
43  + " v.uploaderid, v.isvalid, v.virtualizerconfig, b.displayname, b.description, b.osid, b.virtid, b.ownerid, b.istemplate"
44  + " FROM imageversion v INNER JOIN imagebase b USING (imagebaseid)"
45  + " WHERE v.imageversionid = :imageversionid" );
46  stmt.setString( "imageversionid", imageVersionId );
47  ResultSet rs = stmt.executeQuery();
48  if ( !rs.next() )
49  return null;
50  ImagePublishDataEx img = new ImagePublishDataEx();
51  img.imageVersionId = rs.getString( "imageversionid" );
52  img.imageBaseId = rs.getString( "imagebaseid" );
53  img.createTime = rs.getLong( "createtime" );
54  img.fileSize = rs.getLong( "filesize" );
55  img.uploader = DbUser.getUserInfoOrNull( connection, rs.getString( "uploaderid" ) );
56  img.imageName = rs.getString( "displayname" );
57  img.description = rs.getString( "description" );
58  img.osId = rs.getInt( "osid" );
59  img.virtId = rs.getString( "virtid" );
60  img.owner = DbUser.getUserInfoOrNull( connection, rs.getString( "ownerid" ) );
61  img.isTemplate = rs.getBoolean( "istemplate" );
62  img.machineDescription = ByteBuffer.wrap( rs.getBytes( "virtualizerconfig" ) );
63  // Ex
64  img.exImagePath = rs.getString( "filepath" );
65  img.exIsValid = rs.getBoolean( "isvalid" );
66  return img;
67  } catch ( SQLException e ) {
68  LOGGER.error( "Query failed in DbImage.getImageVersion()", e );
69  throw e;
70  }
71  }
72 
73  public static void createImageBase( ImagePublishData img ) throws TInvocationException
74  {
75  // Input seems valid
76  try ( MysqlConnection connection = Database.getConnection() ) {
77  MysqlStatement stmt = connection.prepareStatement( "SELECT virtid FROM imagebase WHERE imagebaseid = :baseid" );
78  stmt.setString( "baseid", img.imageBaseId );
79  ResultSet rs = stmt.executeQuery();
80  if ( rs.next() ) {
81  if ( !img.virtId.equals( rs.getString( "virtid" ) ) ) {
82  throw new TInvocationException( InvocationError.INVALID_DATA, "Virtualizer id mismatch" );
83  }
84  MysqlStatement stmt2 = connection.prepareStatement( "UPDATE imagebase SET"
85  + " displayname = :displayname, updaterid = :updaterid,"
86  + " description = :description, osid = :osid, updatetime = UNIX_TIMESTAMP(),"
87  + " istemplate = :istemplate WHERE imagebaseid = :baseid" );
88  stmt2.setString( "baseid", img.imageBaseId );
89  stmt2.setString( "displayname", img.imageName );
90  stmt2.setString( "updaterid", img.uploader.userId );
91  stmt2.setString( "description", img.description );
92  stmt2.setInt( "osid", img.osId );
93  stmt2.setBoolean( "istemplate", img.isTemplate );
94  stmt2.executeUpdate();
95  } else {
96  MysqlStatement stmt2 = connection.prepareStatement( "INSERT INTO imagebase"
97  + " (imagebaseid, latestversionid, displayname, description, osid,"
98  + " virtid, createtime, updatetime, ownerid, updaterid, istemplate)"
99  + " VALUES "
100  + " (:imagebaseid, NULL, :displayname, :description, :osid,"
101  + " :virtid, :createtime, UNIX_TIMESTAMP(), :ownerid, :updaterid, :istemplate)" );
102  stmt2.setString( "imagebaseid", img.imageBaseId );
103  stmt2.setString( "displayname", img.imageName );
104  stmt2.setString( "description", img.description );
105  stmt2.setInt( "osid", img.osId );
106  stmt2.setString( "virtid", img.virtId );
107  stmt2.setLong( "createtime", img.createTime );
108  stmt2.setString( "ownerid", img.owner.userId );
109  stmt2.setString( "updaterid", img.uploader.userId );
110  stmt2.setBoolean( "istemplate", img.isTemplate );
111  stmt2.executeUpdate();
112  }
113  connection.commit();
114  } catch ( SQLException e ) {
115  LOGGER.error( "Query failed in DbImage.createImageBase()", e );
116  throw new TInvocationException( InvocationError.INTERNAL_SERVER_ERROR, "Database boo-boo" );
117  }
118  }
119 
120  public static void createImageVersion( ImagePublishData img, String relLocalPath ) throws SQLException
121  {
122  try ( MysqlConnection connection = Database.getConnection() ) {
123  // Insert version
124  MysqlStatement verStmt = connection.prepareStatement( "INSERT INTO imageversion"
125  + " (imageversionid, imagebaseid, createtime, expiretime, filesize,"
126  + " filepath, uploaderid, isvalid, isprocessed, mastersha1, virtualizerconfig)"
127  + " VALUES "
128  + " (:imageversionid, :imagebaseid, :createtime, :expiretime, :filesize,"
129  + " :filepath, :uploaderid, 0, 0, NULL, :virtualizerconfig)" );
130  verStmt.setString( "imageversionid", img.imageVersionId );
131  verStmt.setString( "imagebaseid", img.imageBaseId );
132  verStmt.setLong( "createtime", img.createTime );
133  verStmt.setLong( "expiretime", Util.unixTime() + Globals.getImageValiditySeconds() );
134  verStmt.setLong( "filesize", img.fileSize );
135  verStmt.setString( "filepath", relLocalPath );
136  verStmt.setString( "uploaderid", img.uploader.userId );
137  verStmt.setBinary( "virtualizerconfig", img.getMachineDescription() );
138  verStmt.execute();
139  connection.commit();
140  } catch ( SQLException e ) {
141  LOGGER.error( "Query failed in DbImage.createImageVersion()", e );
142  throw e;
143  }
144  }
145 
146  public static void markValid( String imageVersionId, boolean isValid ) throws SQLException
147  {
148  try ( MysqlConnection connection = Database.getConnection() ) {
149  MysqlStatement stmt = connection.prepareStatement( "UPDATE imageversion"
150  + " SET isvalid = :isvalid WHERE imageversionid = :imageversionid" );
151  stmt.setBoolean( "isvalid", isValid );
152  stmt.setString( "imageversionid", imageVersionId );
153  stmt.executeUpdate();
154  updateLatestForVersion( connection, imageVersionId );
155  connection.commit();
156  } catch ( SQLException e ) {
157  LOGGER.error( "Query failed in DbImage.markValid()", e );
158  throw e;
159  }
160  }
161 
162  private static void updateLatestForVersion( MysqlConnection connection, String imageVersionId ) throws SQLException
163  {
164  MysqlStatement stmt = connection.prepareStatement( "SELECT imagebaseid FROM imageversion"
165  + " WHERE imageversionid = :imageversionid" );
166  stmt.setString( "imageversionid", imageVersionId );
167  ResultSet rs = stmt.executeQuery();
168  if ( !rs.next() )
169  return;
170  updateLatestForBase( connection, rs.getString( "imagebaseid" ) );
171  }
172 
173  private static void updateLatestForBase( MysqlConnection connection, String imageBaseId ) throws SQLException
174  {
175  MysqlStatement stmt = connection.prepareStatement( "SELECT imageversionid FROM imageversion"
176  + " WHERE isvalid <> 0 AND expiretime > UNIX_TIMESTAMP() AND imagebaseid = :imagebaseid"
177  + " ORDER BY createtime DESC LIMIT 1" );
178  stmt.setString( "imagebaseid", imageBaseId );
179  ResultSet rs = stmt.executeQuery();
180  String latestVersionId = null;
181  if ( rs.next() ) {
182  latestVersionId = rs.getString( "imageversionid" );
183  }
184  MysqlStatement updateLatestRef = connection.prepareStatement( "UPDATE imagebase SET latestversionid = :latestversionid"
185  + " WHERE imagebaseid = :imagebaseid" );
186  updateLatestRef.setString( "latestversionid", latestVersionId );
187  updateLatestRef.setString( "imagebaseid", imageBaseId );
188  updateLatestRef.executeUpdate();
189  MysqlStatement expireStmt = connection.prepareStatement( "UPDATE imageversion SET expiretime = :expiretime"
190  + " WHERE imagebaseid = :imagebaseid AND imageversionid <> :latestversionid" );
191  expireStmt.setString( "imagebaseid", imageBaseId );
192  expireStmt.setString( "latestversionid", latestVersionId );
193  expireStmt.setLong( "expiretime", Util.unixTime() + Globals.getOldImageExpireTimeSeconds() );
194  expireStmt.executeUpdate();
195  }
196 
197  public static List<ImageSummaryRead> getPublicList( int page ) throws SQLException, TInvocationException
198  {
199  if ( page < 0 )
200  throw new TInvocationException( InvocationError.INVALID_DATA, "page must be >= 0" );
201  try ( MysqlConnection connection = Database.getConnection() ) {
202  MysqlStatement stmt = connection.prepareStatement( "SELECT v.imageversionid, v.imagebaseid, v.createtime, v.filesize,"
203  + " v.uploaderid, b.displayname, b.description, b.osid, b.virtid, b.ownerid, b.istemplate FROM imagebase b"
204  + " INNER JOIN imageversion v ON (b.latestversionid = v.imageversionid)"
205  + " WHERE v.isvalid = 1"
206  + " ORDER BY imageversionid " + Paginator.limitStatement( page ) );
207  ResultSet rs = stmt.executeQuery();
208  List<ImageSummaryRead> list = new ArrayList<>();
209  while ( rs.next() ) {
210  ImageSummaryRead img = new ImageSummaryRead();
211  img.createTime = rs.getLong( "createtime" );
212  //img.description = rs.getString( "description" );
213  img.fileSize = rs.getLong( "filesize" );
214  img.imageBaseId = rs.getString( "imagebaseid" );
215  img.imageName = rs.getString( "displayname" );
216  img.latestVersionId = rs.getString( "imageversionid" );
217  img.isTemplate = rs.getBoolean( "istemplate" );
218  img.osId = rs.getInt( "osid" );
219  img.ownerId = rs.getString( "ownerid" );
220  //img.software = rs.get( "" ); TODO
221  //img.tags = rs.get( "" ); TODO
222  img.uploaderId = rs.getString( "uploaderid" );
223  img.virtId = rs.getString( "virtid" );
224  img.userPermissions = emptyPermissions;
225  img.defaultPermissions = emptyPermissions;
226  list.add( img );
227  }
228  return list;
229  } catch ( SQLException e ) {
230  LOGGER.error( "Query failed in DbImage.getPublicList()", e );
231  throw e;
232  }
233  }
234 
235  protected static List<ImageVersionDetails> getImageVersions( MysqlConnection connection, String imageBaseId )
236  throws SQLException
237  {
238  List<ImageVersionDetails> versionList = new ArrayList<>();
239  MysqlStatement stmt = connection.prepareStatement( "SELECT"
240  + " imageversionid, createtime, expiretime, filesize, uploaderid,"
241  + " isprocessed FROM imageversion"
242  + " WHERE imagebaseid = :imagebaseid AND isvalid = 1" );
243  stmt.setString( "imagebaseid", imageBaseId );
244  ResultSet rs = stmt.executeQuery();
245  while ( rs.next() ) {
246  List<String> software = null; // DbSoftwareTag.getImageVersionSoftwareList(connection, imageVersionId);
247  String imageVersionId = rs.getString( "imageversionid" );
248  versionList.add( new ImageVersionDetails( imageVersionId, rs.getLong( "createtime" ),
249  rs.getLong( "expiretime" ), rs.getLong( "filesize" ), rs.getString( "uploaderid" ),
250  true, true,
251  rs.getBoolean( "isprocessed" ), software ) );
252  }
253  stmt.close();
254  return versionList;
255  }
256 
257  public static ImageDetailsRead getImageDetails( String imageBaseId ) throws TNotFoundException, SQLException
258  {
259  try ( MysqlConnection connection = Database.getConnection() ) {
260  MysqlStatement stmt = connection.prepareStatement( "SELECT i.imagebaseid, i.latestversionid, i.displayname,"
261  + " i.description, i.osid, i.virtid, i.createtime, i.updatetime, i.ownerid, i.updaterid, i.istemplate"
262  + " FROM imagebase i"
263  + " WHERE i.imagebaseid = :imagebaseid" );
264  stmt.setString( "imagebaseid", imageBaseId );
265  ResultSet rs = stmt.executeQuery();
266  if ( !rs.next() )
267  throw new TNotFoundException();
268  // Exists:
269  List<String> tags = null; // DbSoftwareTag.getImageTags(connection, imageBaseId);
270  List<ImageVersionDetails> versions = getImageVersions( connection, imageBaseId );
271  ImageDetailsRead image = new ImageDetailsRead( rs.getString( "imagebaseid" ),
272  rs.getString( "latestversionid" ), versions, rs.getString( "displayname" ),
273  rs.getString( "description" ), tags, rs.getInt( "osid" ), rs.getString( "virtid" ),
274  rs.getLong( "createtime" ), rs.getLong( "updatetime" ), rs.getString( "ownerid" ),
275  rs.getString( "updaterid" ), ShareMode.FROZEN,
276  rs.getBoolean( "istemplate" ), emptyPermissions );
277  image.userPermissions = emptyPermissions;
278  return image;
279  } catch ( SQLException e ) {
280  LOGGER.error( "Query failed in DbImage.getImageDetails()", e );
281  throw e;
282  }
283  }
284 
285 }
static long getImageValiditySeconds()
Definition: Globals.java:120
static List< ImageSummaryRead > getPublicList(int page)
Definition: DbImage.java:197
static ImageDetailsRead getImageDetails(String imageBaseId)
Definition: DbImage.java:257
static String limitStatement(int page)
Definition: Paginator.java:8
static List< ImageVersionDetails > getImageVersions(MysqlConnection connection, String imageBaseId)
Definition: DbImage.java:235
static UserInfo getUserInfoOrNull(MysqlConnection connection, String userId)
Definition: DbUser.java:78
static void updateLatestForVersion(MysqlConnection connection, String imageVersionId)
Definition: DbImage.java:162
boolean execute()
Executes the statement.
static MysqlConnection getConnection()
Get a connection to the database.
Definition: Database.java:92
ResultSet executeQuery()
Executes the statement, which must be a query.
Representing an image in the database.
Definition: DbImage.java:32
Represents a user that can login against the masterserver.
Definition: DbUser.java:22
static ImagePublishDataEx getImageVersion(String imageVersionId)
Definition: DbImage.java:39
static final ImagePermissions emptyPermissions
Definition: DbImage.java:37
int executeUpdate()
Executes the statement, which must be an SQL INSERT, UPDATE or DELETE statement; or an SQL statement ...
void setInt(String name, int value)
Sets a parameter.
static void createImageVersion(ImagePublishData img, String relLocalPath)
Definition: DbImage.java:120
Class to hold global constants and properties from 'config/global.properties'.
Definition: Globals.java:16
void setBoolean(String name, boolean value)
Sets a parameter.
void setString(String name, String value)
Sets a parameter.
Class for creating PreparedStatements with named parameters.
static long getOldImageExpireTimeSeconds()
Definition: Globals.java:126
void setBinary(String name, byte[] value)
Sets a parameter.
static void markValid(String imageVersionId, boolean isValid)
Definition: DbImage.java:146
Some utilities to make our lives easier.
Definition: Util.java:18
static void updateLatestForBase(MysqlConnection connection, String imageBaseId)
Definition: DbImage.java:173
void setLong(String name, long value)
Sets a parameter.
static void createImageBase(ImagePublishData img)
Definition: DbImage.java:73