Skip to content

Commit 0d2f3d6

Browse files
committed
dont download templates to read-only storages
1 parent 8eb162c commit 0d2f3d6

File tree

4 files changed

+45
-3
lines changed

4 files changed

+45
-3
lines changed

engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/TemplateServiceImpl.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
import org.apache.cloudstack.storage.command.DeleteCommand;
6565
import org.apache.cloudstack.storage.datastore.DataObjectManager;
6666
import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
67+
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
6768
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
6869
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
6970
import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
@@ -163,6 +164,8 @@ public class TemplateServiceImpl implements TemplateService {
163164
TemplateDataFactory imageFactory;
164165
@Inject
165166
StorageOrchestrationService storageOrchestrator;
167+
@Inject
168+
ImageStoreDao dataStoreDao;
166169

167170
class TemplateOpContext<T> extends AsyncRpcContext<T> {
168171
final TemplateObject template;
@@ -295,6 +298,12 @@ public void handleSysTemplateDownload(HypervisorType hostHyper, Long dcId) {
295298
}
296299

297300
protected boolean shouldDownloadTemplateToStore(VMTemplateVO template, DataStore store) {
301+
if (dataStoreDao.findById(store.getId()).isReadonly()) {
302+
logger.debug("Template [{}] will not be download to image store [{}] because this store is marked as read-only.", template.getUniqueName(),
303+
store.getName());
304+
return false;
305+
}
306+
298307
Long zoneId = store.getScope().getScopeId();
299308
DataStore directedStore = _tmpltMgr.verifyHeuristicRulesForZone(template, zoneId);
300309
if (directedStore != null && store.getId() != directedStore.getId()) {

engine/storage/image/src/test/java/org/apache/cloudstack/storage/image/TemplateServiceImplTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
3333
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
3434
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
35+
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
36+
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
3537
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
3638
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
3739
import org.apache.cloudstack.storage.image.store.TemplateObject;
@@ -104,6 +106,12 @@ public class TemplateServiceImplTest {
104106
@Mock
105107
DataCenterDao _dcDao;
106108

109+
@Mock
110+
ImageStoreDao imageStore;
111+
112+
@Mock
113+
ImageStoreVO imageMock;
114+
107115
Map<String, TemplateProp> templatesInSourceStore = new HashMap<>();
108116

109117
@Before
@@ -119,45 +127,59 @@ public void setUp() {
119127
Mockito.doReturn(templateInfoMock).when(templateDataFactoryMock).getTemplate(2L, sourceStoreMock);
120128
Mockito.doReturn(3L).when(dataStoreMock).getId();
121129
Mockito.doReturn(zoneScopeMock).when(dataStoreMock).getScope();
130+
Mockito.when(imageStore.findById(3L)).thenReturn(imageMock);
122131
}
123132

124133
@Test
125134
public void shouldDownloadTemplateToStoreTestSkipsTemplateDirectedToAnotherStorage() {
126135
DataStore destinedStore = Mockito.mock(DataStore.class);
136+
Mockito.when(imageMock.isReadonly()).thenReturn(false);
127137
Mockito.doReturn(dataStoreMock.getId() + 1L).when(destinedStore).getId();
128138
Mockito.when(templateManagerMock.verifyHeuristicRulesForZone(tmpltMock, zoneScopeMock.getScopeId())).thenReturn(destinedStore);
129139
Assert.assertFalse(templateService.shouldDownloadTemplateToStore(tmpltMock, dataStoreMock));
130140
}
131141

132142
@Test
133143
public void shouldDownloadTemplateToStoreTestDownloadsPublicTemplate() {
144+
Mockito.when(imageMock.isReadonly()).thenReturn(false);
134145
Mockito.when(tmpltMock.isPublicTemplate()).thenReturn(true);
135146
Assert.assertTrue(templateService.shouldDownloadTemplateToStore(tmpltMock, dataStoreMock));
136147
}
137148

138149
@Test
139150
public void shouldDownloadTemplateToStoreTestDownloadsFeaturedTemplate() {
151+
Mockito.when(imageMock.isReadonly()).thenReturn(false);
140152
Mockito.when(tmpltMock.isFeatured()).thenReturn(true);
141153
Assert.assertTrue(templateService.shouldDownloadTemplateToStore(tmpltMock, dataStoreMock));
142154
}
143155

144156
@Test
145157
public void shouldDownloadTemplateToStoreTestDownloadsSystemTemplate() {
158+
Mockito.when(imageMock.isReadonly()).thenReturn(false);
146159
Mockito.when(tmpltMock.getTemplateType()).thenReturn(Storage.TemplateType.SYSTEM);
147160
Assert.assertTrue(templateService.shouldDownloadTemplateToStore(tmpltMock, dataStoreMock));
148161
}
149162

150163
@Test
151164
public void shouldDownloadTemplateToStoreTestDownloadsPrivateNoRefTemplate() {
165+
Mockito.when(imageMock.isReadonly()).thenReturn(false);
152166
Assert.assertTrue(templateService.shouldDownloadTemplateToStore(tmpltMock, dataStoreMock));
153167
}
154168

155169
@Test
156170
public void shouldDownloadTemplateToStoreTestSkipsPrivateExistingTemplate() {
171+
Mockito.when(imageMock.isReadonly()).thenReturn(false);
157172
Mockito.when(templateDataStoreDao.findByTemplateZone(tmpltMock.getId(), zoneScopeMock.getScopeId(), DataStoreRole.Image)).thenReturn(Mockito.mock(TemplateDataStoreVO.class));
158173
Assert.assertFalse(templateService.shouldDownloadTemplateToStore(tmpltMock, dataStoreMock));
159174
}
160175

176+
@Test
177+
public void shouldDownloadTemplateToStoreTestSkipsWhenStorageIsReadOnly() {
178+
Mockito.when(imageMock.isReadonly()).thenReturn(true);
179+
Assert.assertFalse(templateService.shouldDownloadTemplateToStore(tmpltMock, dataStoreMock));
180+
181+
}
182+
161183
@Test
162184
public void tryDownloadingTemplateToImageStoreTestDownloadsTemplateWhenUrlIsNotNull() {
163185
Mockito.doReturn("url").when(tmpltMock).getUrl();

engine/storage/src/main/java/org/apache/cloudstack/storage/image/BaseImageStoreDriverImpl.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import org.apache.cloudstack.storage.command.CommandResult;
4545
import org.apache.cloudstack.storage.command.CopyCommand;
4646
import org.apache.cloudstack.storage.command.DeleteCommand;
47+
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
4748
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
4849
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
4950
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
@@ -126,6 +127,8 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver {
126127
AgentManager agentMgr;
127128
@Inject
128129
DataStoreManager dataStoreManager;
130+
@Inject
131+
ImageStoreDao dataStoreDao;
129132

130133
protected String _proxy = null;
131134

@@ -175,10 +178,13 @@ public void createAsync(DataStore dataStore, DataObject data, AsyncCompletionCal
175178
AsyncCallbackDispatcher<BaseImageStoreDriverImpl, DownloadAnswer> caller = AsyncCallbackDispatcher.create(this);
176179
caller.setContext(context);
177180
if (data.getType() == DataObjectType.TEMPLATE) {
178-
caller.setCallback(caller.getTarget().createTemplateAsyncCallback(null, null));
179-
if (logger.isDebugEnabled()) {
180-
logger.debug("Downloading template to data store {}", dataStore);
181+
if (dataStoreDao.findById(dataStore.getId()).isReadonly()) {
182+
logger.debug("Template [{}] will not be download to image store [{}] because this store is marked as read-only.", data.getName(),
183+
dataStore.getName());
184+
return;
181185
}
186+
caller.setCallback(caller.getTarget().createTemplateAsyncCallback(null, null));
187+
logger.debug("Downloading template [{}] to data store [{}].", data.getName(), dataStore.getName());
182188
_downloadMonitor.downloadTemplateToStorage(data, caller);
183189
} else if (data.getType() == DataObjectType.VOLUME) {
184190
caller.setCallback(caller.getTarget().createVolumeAsyncCallback(null, null));

server/src/main/java/com/cloud/template/HypervisorTemplateAdapter.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,11 @@ protected boolean isZoneAndImageStoreAvailable(DataStore imageStore, Long zoneId
338338
return false;
339339
}
340340

341+
if (_imgStoreDao.findById(imageStore.getId()).isReadonly()) {
342+
logger.info("Image store [{}] is marked as read-only. Skip downloading template to this image store.", imageStore);
343+
return false;
344+
}
345+
341346
if (!_statsCollector.imageStoreHasEnoughCapacity(imageStore)) {
342347
logger.info("Image store doesn't have enough capacity. Skip downloading template to this image store [{}].", imageStore);
343348
return false;

0 commit comments

Comments
 (0)