Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/scripts/sql/manage_storage.php
12241 views
1
#!/usr/bin/env php
2
<?php
3
4
$root = dirname(dirname(dirname(__FILE__)));
5
require_once $root.'/scripts/init/init-setup.php';
6
7
$args = new PhutilArgumentParser($argv);
8
$args->setTagline(pht('manage storage and schemata'));
9
$args->setSynopsis(<<<EOHELP
10
**storage** __workflow__ [__options__]
11
Manage database storage and schema versioning.
12
13
**storage** upgrade
14
Initialize or upgrade storage.
15
16
**storage** upgrade --user __root__ --password __hunter2__
17
Use administrative credentials for schema changes.
18
EOHELP
19
);
20
$args->parseStandardArguments();
21
22
$default_namespace = PhabricatorLiskDAO::getDefaultStorageNamespace();
23
24
try {
25
$args->parsePartial(
26
array(
27
array(
28
'name' => 'force',
29
'short' => 'f',
30
'help' => pht(
31
'Do not prompt before performing dangerous operations.'),
32
),
33
array(
34
'name' => 'host',
35
'param' => 'hostname',
36
'help' => pht(
37
'Operate on the database server identified by __hostname__.'),
38
),
39
array(
40
'name' => 'ref',
41
'param' => 'ref',
42
'help' => pht(
43
'Operate on the database identified by __ref__.'),
44
),
45
array(
46
'name' => 'user',
47
'short' => 'u',
48
'param' => 'username',
49
'help' => pht(
50
'Connect with __username__ instead of the configured default.'),
51
),
52
array(
53
'name' => 'password',
54
'short' => 'p',
55
'param' => 'password',
56
'help' => pht('Use __password__ instead of the configured default.'),
57
),
58
array(
59
'name' => 'namespace',
60
'param' => 'name',
61
'default' => $default_namespace,
62
'help' => pht(
63
"Use namespace __namespace__ instead of the configured ".
64
"default ('%s'). This is an advanced feature used by unit tests; ".
65
"you should not normally use this flag.",
66
$default_namespace),
67
),
68
array(
69
'name' => 'dryrun',
70
'help' => pht(
71
'Do not actually change anything, just show what would be changed.'),
72
),
73
array(
74
'name' => 'disable-utf8mb4',
75
'help' => pht(
76
'Disable %s, even if the database supports it. This is an '.
77
'advanced feature used for testing internal changes; you '.
78
'should not normally use this flag.',
79
'utf8mb4'),
80
),
81
));
82
} catch (PhutilArgumentUsageException $ex) {
83
$args->printUsageException($ex);
84
exit(77);
85
}
86
87
// First, test that the Phabricator configuration is set up correctly. After
88
// we know this works we'll test any administrative credentials specifically.
89
90
$refs = PhabricatorDatabaseRef::getActiveDatabaseRefs();
91
if (!$refs) {
92
throw new PhutilArgumentUsageException(
93
pht('No databases are configured.'));
94
}
95
96
$host = $args->getArg('host');
97
$ref_key = $args->getArg('ref');
98
if (($host !== null) || ($ref_key !== null)) {
99
if ($host && $ref_key) {
100
throw new PhutilArgumentUsageException(
101
pht(
102
'Use "--host" or "--ref" to select a database, but not both.'));
103
}
104
105
$refs = PhabricatorDatabaseRef::getActiveDatabaseRefs();
106
107
$possible_refs = array();
108
foreach ($refs as $possible_ref) {
109
if ($host && ($possible_ref->getHost() == $host)) {
110
$possible_refs[] = $possible_ref;
111
break;
112
}
113
if ($ref_key && ($possible_ref->getRefKey() == $ref_key)) {
114
$possible_refs[] = $possible_ref;
115
break;
116
}
117
}
118
119
if (!$possible_refs) {
120
if ($host) {
121
throw new PhutilArgumentUsageException(
122
pht(
123
'There is no configured database on host "%s". This command can '.
124
'only interact with configured databases.',
125
$host));
126
} else {
127
throw new PhutilArgumentUsageException(
128
pht(
129
'There is no configured database with ref "%s". This command can '.
130
'only interact with configured databases.',
131
$ref_key));
132
}
133
}
134
135
if (count($possible_refs) > 1) {
136
throw new PhutilArgumentUsageException(
137
pht(
138
'Host "%s" identifies more than one database. Use "--ref" to select '.
139
'a specific database.',
140
$host));
141
}
142
143
$refs = $possible_refs;
144
}
145
146
$apis = array();
147
foreach ($refs as $ref) {
148
$default_user = $ref->getUser();
149
$default_host = $ref->getHost();
150
$default_port = $ref->getPort();
151
152
$test_api = id(new PhabricatorStorageManagementAPI())
153
->setUser($default_user)
154
->setHost($default_host)
155
->setPort($default_port)
156
->setPassword($ref->getPass())
157
->setNamespace($args->getArg('namespace'));
158
159
try {
160
queryfx(
161
$test_api->getConn(null),
162
'SELECT 1');
163
} catch (AphrontQueryException $ex) {
164
$message = phutil_console_format(
165
"**%s**\n\n%s\n\n%s\n\n%s\n\n**%s**: %s\n",
166
pht('MySQL Credentials Not Configured'),
167
pht(
168
'Unable to connect to MySQL using the configured credentials. '.
169
'You must configure standard credentials before you can upgrade '.
170
'storage. Run these commands to set up credentials:'),
171
" $ ./bin/config set mysql.host __host__\n".
172
" $ ./bin/config set mysql.user __username__\n".
173
" $ ./bin/config set mysql.pass __password__",
174
pht(
175
'These standard credentials are separate from any administrative '.
176
'credentials provided to this command with __%s__ or '.
177
'__%s__, and must be configured correctly before you can proceed.',
178
'--user',
179
'--password'),
180
pht('Raw MySQL Error'),
181
$ex->getMessage());
182
echo phutil_console_wrap($message);
183
exit(1);
184
}
185
186
if ($args->getArg('password') === null) {
187
// This is already a PhutilOpaqueEnvelope.
188
$password = $ref->getPass();
189
} else {
190
// Put this in a PhutilOpaqueEnvelope.
191
$password = new PhutilOpaqueEnvelope($args->getArg('password'));
192
PhabricatorEnv::overrideConfig('mysql.pass', $args->getArg('password'));
193
}
194
195
$selected_user = $args->getArg('user');
196
if ($selected_user === null) {
197
$selected_user = $default_user;
198
}
199
200
$api = id(new PhabricatorStorageManagementAPI())
201
->setUser($selected_user)
202
->setHost($default_host)
203
->setPort($default_port)
204
->setPassword($password)
205
->setNamespace($args->getArg('namespace'))
206
->setDisableUTF8MB4($args->getArg('disable-utf8mb4'));
207
PhabricatorEnv::overrideConfig('mysql.user', $api->getUser());
208
209
$ref->setUser($selected_user);
210
$ref->setPass($password);
211
212
try {
213
queryfx(
214
$api->getConn(null),
215
'SELECT 1');
216
} catch (AphrontQueryException $ex) {
217
$message = phutil_console_format(
218
"**%s**\n\n%s\n\n**%s**: %s\n",
219
pht('Bad Administrative Credentials'),
220
pht(
221
'Unable to connect to MySQL using the administrative credentials '.
222
'provided with the __%s__ and __%s__ flags. Check that '.
223
'you have entered them correctly.',
224
'--user',
225
'--password'),
226
pht('Raw MySQL Error'),
227
$ex->getMessage());
228
echo phutil_console_wrap($message);
229
exit(1);
230
}
231
232
$api->setRef($ref);
233
$apis[] = $api;
234
}
235
236
$workflows = id(new PhutilClassMapQuery())
237
->setAncestorClass('PhabricatorStorageManagementWorkflow')
238
->execute();
239
240
$patches = PhabricatorSQLPatchList::buildAllPatches();
241
242
foreach ($workflows as $workflow) {
243
$workflow->setAPIs($apis);
244
$workflow->setPatches($patches);
245
}
246
247
$workflows[] = new PhutilHelpArgumentWorkflow();
248
249
$args->parseWorkflows($workflows);
250
251