Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/diffusion/management/DiffusionRepositoryStorageManagementPanel.php
13395 views
1
<?php
2
3
final class DiffusionRepositoryStorageManagementPanel
4
extends DiffusionRepositoryManagementPanel {
5
6
const PANELKEY = 'storage';
7
8
public function getManagementPanelLabel() {
9
return pht('Storage');
10
}
11
12
public function getManagementPanelOrder() {
13
return 600;
14
}
15
16
public function getManagementPanelIcon() {
17
$repository = $this->getRepository();
18
19
if ($repository->getAlmanacServicePHID()) {
20
return 'fa-sitemap';
21
} else if ($repository->isHosted()) {
22
return 'fa-database';
23
} else {
24
return 'fa-download';
25
}
26
}
27
28
public function buildManagementPanelCurtain() {
29
$repository = $this->getRepository();
30
$viewer = $this->getViewer();
31
$action_list = $this->newActionList();
32
33
$doc_href = PhabricatorEnv::getDoclink('Cluster: Repositories');
34
35
$action_list->addAction(
36
id(new PhabricatorActionView())
37
->setIcon('fa-book')
38
->setHref($doc_href)
39
->setName(pht('Cluster Documentation')));
40
41
return $this->newCurtainView()
42
->setActionList($action_list);
43
}
44
45
public function buildManagementPanelContent() {
46
return array(
47
$this->buildStorageStatusPanel(),
48
$this->buildClusterStatusPanel(),
49
$this->buildRefsStatusPanels(),
50
);
51
}
52
53
private function buildStorageStatusPanel() {
54
$repository = $this->getRepository();
55
$viewer = $this->getViewer();
56
57
$view = id(new PHUIPropertyListView())
58
->setViewer($viewer);
59
60
if ($repository->usesLocalWorkingCopy()) {
61
$storage_path = $repository->getLocalPath();
62
} else {
63
$storage_path = phutil_tag('em', array(), pht('No Local Working Copy'));
64
}
65
66
$service_phid = $repository->getAlmanacServicePHID();
67
if ($service_phid) {
68
$storage_service = $viewer->renderHandle($service_phid);
69
} else {
70
$storage_service = phutil_tag('em', array(), pht('Local'));
71
}
72
73
$view->addProperty(pht('Storage Path'), $storage_path);
74
$view->addProperty(pht('Storage Cluster'), $storage_service);
75
76
return $this->newBox(pht('Storage'), $view);
77
}
78
79
private function buildClusterStatusPanel() {
80
$repository = $this->getRepository();
81
$viewer = $this->getViewer();
82
83
$service_phid = $repository->getAlmanacServicePHID();
84
if ($service_phid) {
85
$service = id(new AlmanacServiceQuery())
86
->setViewer($viewer)
87
->withServiceTypes(
88
array(
89
AlmanacClusterRepositoryServiceType::SERVICETYPE,
90
))
91
->withPHIDs(array($service_phid))
92
->needActiveBindings(true)
93
->executeOne();
94
if (!$service) {
95
// TODO: Viewer may not have permission to see the service, or it may
96
// be invalid? Raise some more useful error here?
97
throw new Exception(pht('Unable to load cluster service.'));
98
}
99
} else {
100
$service = null;
101
}
102
103
Javelin::initBehavior('phabricator-tooltips');
104
105
$rows = array();
106
if ($service) {
107
$bindings = $service->getActiveBindings();
108
$bindings = mgroup($bindings, 'getDevicePHID');
109
110
// This is an unusual read which always comes from the master.
111
if (PhabricatorEnv::isReadOnly()) {
112
$versions = array();
113
} else {
114
$versions = PhabricatorRepositoryWorkingCopyVersion::loadVersions(
115
$repository->getPHID());
116
}
117
118
$versions = mpull($versions, null, 'getDevicePHID');
119
120
$sort = array();
121
foreach ($bindings as $key => $binding_group) {
122
$sort[$key] = id(new PhutilSortVector())
123
->addString(head($binding_group)->getDevice()->getName());
124
}
125
$sort = msortv($sort, 'getSelf');
126
$bindings = array_select_keys($bindings, array_keys($sort)) + $bindings;
127
128
foreach ($bindings as $binding_group) {
129
$any_binding = head($binding_group);
130
131
$binding_icon = 'fa-folder-open green';
132
$binding_tip = pht('Active');
133
134
$binding_icon = id(new PHUIIconView())
135
->setIcon($binding_icon)
136
->addSigil('has-tooltip')
137
->setMetadata(
138
array(
139
'tip' => $binding_tip,
140
));
141
142
$device = $any_binding->getDevice();
143
144
$version = idx($versions, $device->getPHID());
145
if ($version) {
146
$version_number = $version->getRepositoryVersion();
147
148
$href = null;
149
if ($repository->isHosted()) {
150
$href = "/diffusion/pushlog/view/{$version_number}/";
151
} else {
152
$commit = id(new DiffusionCommitQuery())
153
->setViewer($viewer)
154
->withIDs(array($version_number))
155
->executeOne();
156
if ($commit) {
157
$href = $commit->getURI();
158
}
159
}
160
161
if ($href) {
162
$version_number = phutil_tag(
163
'a',
164
array(
165
'href' => $href,
166
),
167
$version_number);
168
}
169
} else {
170
$version_number = '-';
171
}
172
173
if ($version && $version->getIsWriting()) {
174
$is_writing = id(new PHUIIconView())
175
->setIcon('fa-pencil green');
176
} else {
177
$is_writing = id(new PHUIIconView())
178
->setIcon('fa-pencil grey');
179
}
180
181
$write_properties = null;
182
if ($version) {
183
$write_properties = $version->getWriteProperties();
184
if ($write_properties) {
185
try {
186
$write_properties = phutil_json_decode($write_properties);
187
} catch (Exception $ex) {
188
$write_properties = null;
189
}
190
}
191
}
192
193
$last_writer = null;
194
$writer_epoch = null;
195
if ($write_properties) {
196
$writer_phid = idx($write_properties, 'userPHID');
197
198
if ($writer_phid) {
199
$last_writer = $viewer->renderHandle($writer_phid);
200
}
201
202
$writer_epoch = idx($write_properties, 'epoch');
203
if ($writer_epoch) {
204
$writer_epoch = phabricator_datetime($writer_epoch, $viewer);
205
}
206
}
207
208
$rows[] = array(
209
$binding_icon,
210
phutil_tag(
211
'a',
212
array(
213
'href' => $device->getURI(),
214
),
215
$device->getName()),
216
$version_number,
217
$is_writing,
218
$last_writer,
219
$writer_epoch,
220
);
221
}
222
}
223
224
$table = id(new AphrontTableView($rows))
225
->setNoDataString(pht('This is not a cluster repository.'))
226
->setHeaders(
227
array(
228
null,
229
pht('Device'),
230
pht('Version'),
231
pht('Writing'),
232
pht('Last Writer'),
233
pht('Last Write At'),
234
))
235
->setColumnClasses(
236
array(
237
null,
238
null,
239
null,
240
'right wide',
241
null,
242
'date',
243
));
244
245
return $this->newBox(pht('Cluster Status'), $table);
246
}
247
248
private function buildRefsStatusPanels() {
249
$repository = $this->getRepository();
250
251
$service_phid = $repository->getAlmanacServicePHID();
252
if (!$service_phid) {
253
// If this repository isn't clustered, don't bother rendering anything.
254
// There are enough other context clues that another empty panel isn't
255
// useful.
256
return;
257
}
258
259
$all_protocols = array(
260
'http',
261
'https',
262
'ssh',
263
);
264
265
$readable_panel = $this->buildRefsStatusPanel(
266
pht('Readable Service Refs'),
267
array(
268
'neverProxy' => false,
269
'protocols' => $all_protocols,
270
'writable' => false,
271
));
272
273
$writable_panel = $this->buildRefsStatusPanel(
274
pht('Writable Service Refs'),
275
array(
276
'neverProxy' => false,
277
'protocols' => $all_protocols,
278
'writable' => true,
279
));
280
281
return array(
282
$readable_panel,
283
$writable_panel,
284
);
285
}
286
287
private function buildRefsStatusPanel(
288
$title,
289
$options) {
290
291
$repository = $this->getRepository();
292
$viewer = $this->getViewer();
293
294
$caught = null;
295
try {
296
$refs = $repository->getAlmanacServiceRefs($viewer, $options);
297
} catch (Exception $ex) {
298
$caught = $ex;
299
} catch (Throwable $ex) {
300
$caught = $ex;
301
}
302
303
$info_view = null;
304
if ($caught) {
305
$refs = array();
306
$info_view = id(new PHUIInfoView())
307
->setErrors(
308
array(
309
phutil_escape_html_newlines($caught->getMessage()),
310
));
311
}
312
313
$phids = array();
314
foreach ($refs as $ref) {
315
$phids[] = $ref->getDevicePHID();
316
}
317
318
$handles = $viewer->loadHandles($phids);
319
320
$icon_writable = id(new PHUIIconView())
321
->setIcon('fa-pencil', 'green');
322
323
$icon_unwritable = id(new PHUIIconView())
324
->setIcon('fa-times', 'grey');
325
326
$rows = array();
327
foreach ($refs as $ref) {
328
$device_phid = $ref->getDevicePHID();
329
$device_handle = $handles[$device_phid];
330
331
if ($ref->isWritable()) {
332
$writable_icon = $icon_writable;
333
$writable_text = pht('Read/Write');
334
} else {
335
$writable_icon = $icon_unwritable;
336
$writable_text = pht('Read Only');
337
}
338
339
$rows[] = array(
340
$device_handle->renderLink(),
341
$ref->getURI(),
342
$writable_icon,
343
$writable_text,
344
);
345
}
346
347
$table = id(new AphrontTableView($rows))
348
->setNoDataString(pht('No repository service refs available.'))
349
->setHeaders(
350
array(
351
pht('Device'),
352
pht('Internal Service URI'),
353
null,
354
pht('I/O'),
355
))
356
->setColumnClasses(
357
array(
358
null,
359
'wide',
360
'icon',
361
null,
362
));
363
364
$box_view = $this->newBox($title, $table);
365
366
if ($info_view) {
367
$box_view->setInfoView($info_view);
368
}
369
370
return $box_view;
371
}
372
373
}
374
375