gcloud 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data.tar.gz.sig +2 -3
- data/CHANGELOG +4 -0
- data/LICENSE +674 -0
- data/Manifest +111 -0
- data/README.md +4 -3
- data/bin/gcutil +53 -0
- data/gcloud.gemspec +4 -3
- data/packages/gcutil-1.7.1/CHANGELOG +197 -0
- data/packages/gcutil-1.7.1/LICENSE +202 -0
- data/packages/gcutil-1.7.1/VERSION +1 -0
- data/packages/gcutil-1.7.1/gcutil +53 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/LICENSE +23 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/__init__.py +1 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/discovery.py +743 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/errors.py +123 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/ext/__init__.py +0 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/http.py +1443 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/mimeparse.py +172 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/model.py +385 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/schema.py +303 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/__init__.py +1 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/anyjson.py +32 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/appengine.py +528 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/client.py +1139 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/clientsecrets.py +105 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/crypt.py +244 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/django_orm.py +124 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/file.py +107 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/locked_file.py +343 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/multistore_file.py +379 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/tools.py +174 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/uritemplate/__init__.py +147 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/LICENSE +202 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/__init__.py +3 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/__init__.py +3 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/app.py +356 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/appcommands.py +783 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/basetest.py +1260 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/datelib.py +421 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/debug.py +60 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/file_util.py +181 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/resources.py +67 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/run_script_module.py +217 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/setup_command.py +159 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/shellutil.py +49 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/stopwatch.py +204 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/__init__.py +0 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auth_helper.py +140 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auth_helper_test.py +149 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auto_auth.py +130 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auto_auth_test.py +75 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/basic_cmds.py +128 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/basic_cmds_test.py +111 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/command_base.py +1808 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/command_base_test.py +1651 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/compute/v1beta13.json +2851 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/compute/v1beta14.json +3361 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/disk_cmds.py +342 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/disk_cmds_test.py +474 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/firewall_cmds.py +344 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/firewall_cmds_test.py +231 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/flags_cache.py +274 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/gcutil +89 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/gcutil_logging.py +69 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/image_cmds.py +262 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/image_cmds_test.py +172 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/instance_cmds.py +1506 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/instance_cmds_test.py +1904 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/kernel_cmds.py +91 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/kernel_cmds_test.py +56 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/machine_type_cmds.py +106 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/machine_type_cmds_test.py +59 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/metadata.py +96 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/metadata_lib.py +357 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/metadata_test.py +84 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/mock_api.py +420 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/mock_metadata.py +58 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/move_cmds.py +824 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/move_cmds_test.py +307 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/network_cmds.py +178 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/network_cmds_test.py +133 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/operation_cmds.py +181 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/operation_cmds_test.py +196 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/path_initializer.py +38 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/project_cmds.py +173 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/project_cmds_test.py +111 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/scopes.py +61 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/scopes_test.py +50 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/snapshot_cmds.py +276 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/snapshot_cmds_test.py +260 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/ssh_keys.py +266 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/ssh_keys_test.py +128 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/table_formatter.py +563 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/thread_pool.py +188 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/thread_pool_test.py +88 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/utils.py +208 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/utils_test.py +193 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/version.py +17 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/version_checker.py +246 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/version_checker_test.py +271 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/zone_cmds.py +151 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/zone_cmds_test.py +60 -0
- data/packages/gcutil-1.7.1/lib/httplib2/LICENSE +21 -0
- data/packages/gcutil-1.7.1/lib/httplib2/httplib2/__init__.py +1630 -0
- data/packages/gcutil-1.7.1/lib/httplib2/httplib2/cacerts.txt +714 -0
- data/packages/gcutil-1.7.1/lib/httplib2/httplib2/iri2uri.py +110 -0
- data/packages/gcutil-1.7.1/lib/httplib2/httplib2/socks.py +438 -0
- data/packages/gcutil-1.7.1/lib/iso8601/LICENSE +20 -0
- data/packages/gcutil-1.7.1/lib/iso8601/iso8601/__init__.py +1 -0
- data/packages/gcutil-1.7.1/lib/iso8601/iso8601/iso8601.py +102 -0
- data/packages/gcutil-1.7.1/lib/iso8601/iso8601/test_iso8601.py +111 -0
- data/packages/gcutil-1.7.1/lib/python_gflags/AUTHORS +2 -0
- data/packages/gcutil-1.7.1/lib/python_gflags/LICENSE +28 -0
- data/packages/gcutil-1.7.1/lib/python_gflags/gflags.py +2862 -0
- data/packages/gcutil-1.7.1/lib/python_gflags/gflags2man.py +544 -0
- data/packages/gcutil-1.7.1/lib/python_gflags/gflags_validators.py +187 -0
- metadata +118 -5
- metadata.gz.sig +0 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
#!/usr/bin/python
|
|
2
|
+
#
|
|
3
|
+
# Copyright 2012 Google Inc. All Rights Reserved.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
"""Unit tests for the move commands."""
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
import path_initializer
|
|
22
|
+
path_initializer.InitializeSysPath()
|
|
23
|
+
|
|
24
|
+
import copy
|
|
25
|
+
import uuid
|
|
26
|
+
|
|
27
|
+
from google.apputils import app
|
|
28
|
+
import gflags as flags
|
|
29
|
+
import unittest
|
|
30
|
+
|
|
31
|
+
from gcutil import command_base
|
|
32
|
+
from gcutil import mock_api
|
|
33
|
+
from gcutil import move_cmds
|
|
34
|
+
|
|
35
|
+
FLAGS = flags.FLAGS
|
|
36
|
+
|
|
37
|
+
class MoveInstancesBaseTestCase(unittest.TestCase):
|
|
38
|
+
|
|
39
|
+
def setUp(self):
|
|
40
|
+
self.flag_values = copy.deepcopy(FLAGS)
|
|
41
|
+
self.command = self._CreateCommand()
|
|
42
|
+
self.api = mock_api.MockApi()
|
|
43
|
+
self.command.SetFlags(self.flag_values)
|
|
44
|
+
self.command.SetApi(self.api)
|
|
45
|
+
|
|
46
|
+
def _CreateCommand(self):
|
|
47
|
+
return move_cmds.MoveInstances('basemoveinstances', self.flag_values)
|
|
48
|
+
|
|
49
|
+
class MoveInstancesBaseTest(MoveInstancesBaseTestCase):
|
|
50
|
+
|
|
51
|
+
cmd_name = 'moveinstancesbase'
|
|
52
|
+
|
|
53
|
+
def testExtractAvailableQuota(self):
|
|
54
|
+
project_quota = [
|
|
55
|
+
{'metric': 'INSTANCES',
|
|
56
|
+
'usage': 5.0,
|
|
57
|
+
'limit': 10.0},
|
|
58
|
+
{'metric': 'CPUS',
|
|
59
|
+
'usage': 40.0,
|
|
60
|
+
'limit': 0}, # Quota was changed after resource-creation.
|
|
61
|
+
{'metric': 'EPHEMERAL_ADDRESSES',
|
|
62
|
+
'usage': 5.0,
|
|
63
|
+
'limit': 10.0},
|
|
64
|
+
{'metric': 'DISKS',
|
|
65
|
+
'usage': 7.0,
|
|
66
|
+
'limit': 10.0},
|
|
67
|
+
{'metric': 'DISKS_TOTAL_GB',
|
|
68
|
+
'usage': 40.0,
|
|
69
|
+
'limit': 100.0},
|
|
70
|
+
{'metric': 'SNAPSHOTS',
|
|
71
|
+
'usage': 3.0,
|
|
72
|
+
'limit': 100.0},
|
|
73
|
+
{'metric': 'NETWORKS',
|
|
74
|
+
'usage': 2.0,
|
|
75
|
+
'limit': 10.0},
|
|
76
|
+
{'metric': 'FIREWALLS',
|
|
77
|
+
'usage': 3.0,
|
|
78
|
+
'limit': 10.0},
|
|
79
|
+
{'metric': 'IMAGES',
|
|
80
|
+
'usage': 9.0,
|
|
81
|
+
'limit': 10.0}]
|
|
82
|
+
|
|
83
|
+
zone_quota = [
|
|
84
|
+
{'metric': 'INSTANCES',
|
|
85
|
+
'usage': 3.0,
|
|
86
|
+
'limit': 10.0},
|
|
87
|
+
{'metric': 'CPUS',
|
|
88
|
+
'usage': 3.0,
|
|
89
|
+
'limit': 10.0},
|
|
90
|
+
{'metric': 'DISKS',
|
|
91
|
+
'usage': 2.0,
|
|
92
|
+
'limit': 10.0},
|
|
93
|
+
{'metric': 'DISKS_TOTAL_GB',
|
|
94
|
+
'usage': 22.0,
|
|
95
|
+
'limit': 25.0}]
|
|
96
|
+
|
|
97
|
+
requirements = {
|
|
98
|
+
'INSTANCES': 2.0,
|
|
99
|
+
'CPUS': 2.0,
|
|
100
|
+
'DISKS_TOTAL_GB': 32.0,
|
|
101
|
+
'SNAPSHOTS': 3.0,
|
|
102
|
+
'DISKS': 3.0}
|
|
103
|
+
|
|
104
|
+
expected = {
|
|
105
|
+
'INSTANCES': 7.0,
|
|
106
|
+
'CPUS': -38.0,
|
|
107
|
+
'DISKS_TOTAL_GB': 3.0,
|
|
108
|
+
'SNAPSHOTS': 97.0,
|
|
109
|
+
'DISKS': 6.0}
|
|
110
|
+
|
|
111
|
+
self.assertEqual(self.command._ExtractAvailableQuota(
|
|
112
|
+
project_quota, zone_quota, requirements), expected)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class MoveInstancesTest(MoveInstancesBaseTestCase):
|
|
116
|
+
|
|
117
|
+
def _CreateCommand(self):
|
|
118
|
+
return move_cmds.MoveInstances('moveinstances', self.flag_values)
|
|
119
|
+
|
|
120
|
+
def testServiceVersionValidation(self):
|
|
121
|
+
for version in command_base.SUPPORTED_VERSIONS:
|
|
122
|
+
if version == 'v1beta14':
|
|
123
|
+
break
|
|
124
|
+
|
|
125
|
+
self.flag_values.source_zone = 'src-zone'
|
|
126
|
+
self.flag_values.destination_zone = 'dest-zone'
|
|
127
|
+
self.flag_values.service_version = version
|
|
128
|
+
self.assertRaises(app.UsageError, self.command.Handle, ['.*'])
|
|
129
|
+
|
|
130
|
+
def testFlagValidationWithNoSourceZone(self):
|
|
131
|
+
self.flag_values.destination_zone = 'dest-zone'
|
|
132
|
+
self.flag_values.service_version = 'v1beta14'
|
|
133
|
+
self.assertRaises(app.UsageError, self.command.Handle, ['.*'])
|
|
134
|
+
|
|
135
|
+
def testFlagValidationWithNoDestinationZone(self):
|
|
136
|
+
self.flag_values.source_zone = 'src-zone'
|
|
137
|
+
self.flag_values.service_version = 'v1beta14'
|
|
138
|
+
self.assertRaises(app.UsageError, self.command.Handle, ['.*'])
|
|
139
|
+
|
|
140
|
+
def testFlagValidationWithNoSameSrcAndDest(self):
|
|
141
|
+
self.flag_values.source_zone = 'my-zone'
|
|
142
|
+
self.flag_values.destination_zone = 'my-zone'
|
|
143
|
+
self.assertRaises(app.UsageError, self.command.Handle, ['.*'])
|
|
144
|
+
|
|
145
|
+
def testGenerateSnapshotNames(self):
|
|
146
|
+
test_cases = (
|
|
147
|
+
[],
|
|
148
|
+
['disk-0'],
|
|
149
|
+
['disk-1', 'disk2', 'disk3'])
|
|
150
|
+
|
|
151
|
+
for arg in test_cases:
|
|
152
|
+
res = self.command._GenerateSnapshotNames(arg)
|
|
153
|
+
self.assertEqual(len(res), len(arg))
|
|
154
|
+
self.assertEqual(sorted(res.keys()), sorted(arg))
|
|
155
|
+
for val in res.values():
|
|
156
|
+
self.assertTrue(isinstance(val, basestring))
|
|
157
|
+
self.assertTrue(val.startswith('snapshot-'))
|
|
158
|
+
try:
|
|
159
|
+
uuid.UUID(val[len('snapshot-'):])
|
|
160
|
+
except ValueError:
|
|
161
|
+
self.fail('Value generated does not include valid UUID.')
|
|
162
|
+
|
|
163
|
+
def _GenerateInstanceResources(self, num, prefix='instance'):
|
|
164
|
+
template = {
|
|
165
|
+
'status': 'RUNNING',
|
|
166
|
+
'kind': 'compute#instance',
|
|
167
|
+
'machineType': 'https://googleapis.com/compute/.../n1-standard-1',
|
|
168
|
+
'zone': 'https://googleapis.com/compute/.../zones/my-zone',
|
|
169
|
+
'tags': [],
|
|
170
|
+
'image': 'https://googleapis.com/compute/.../images/gcel',
|
|
171
|
+
'disks': [
|
|
172
|
+
{
|
|
173
|
+
'index': 0,
|
|
174
|
+
'kind': 'compute#instanceDisk',
|
|
175
|
+
'type': 'EPHEMERAL',
|
|
176
|
+
'mode': 'READ_WRITE'
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
'index': 1,
|
|
180
|
+
'kind': 'compute#attachedDisk',
|
|
181
|
+
'mode': 'READ_ONLY',
|
|
182
|
+
'type': 'PERSISTENT'
|
|
183
|
+
}
|
|
184
|
+
],
|
|
185
|
+
'networkInterfaces': [
|
|
186
|
+
{
|
|
187
|
+
'networkIP': '10.211.197.175',
|
|
188
|
+
'kind': 'compute#instanceNetworkInterface',
|
|
189
|
+
'accessConfigs': [
|
|
190
|
+
{
|
|
191
|
+
'type': 'ONE_TO_ONE_NAT',
|
|
192
|
+
'name': 'External NAT',
|
|
193
|
+
'natIP': '173.255.120.98'
|
|
194
|
+
}
|
|
195
|
+
],
|
|
196
|
+
'name': 'nic0',
|
|
197
|
+
'network': 'https://googleapis.com/compute/.../networks/default'
|
|
198
|
+
}
|
|
199
|
+
],
|
|
200
|
+
'id': '12884714477555140369'}
|
|
201
|
+
|
|
202
|
+
res = []
|
|
203
|
+
for i in xrange(num):
|
|
204
|
+
instance = copy.deepcopy(template)
|
|
205
|
+
instance['name'] = '%s-%s' % (prefix, i)
|
|
206
|
+
instance['selfLink'] = (
|
|
207
|
+
'https://googleapis.com/compute/.../instances/%s' % instance['name'])
|
|
208
|
+
instance['disks'][1]['deviceName'] = instance['name']
|
|
209
|
+
instance['disks'][1]['source'] = (
|
|
210
|
+
'https://www.googleapis.com/compute/.../disks/%s' % instance['name'])
|
|
211
|
+
res.append(instance)
|
|
212
|
+
return res
|
|
213
|
+
|
|
214
|
+
def testCheckInstancePreconditionsWithNoMatchingInstances(self):
|
|
215
|
+
self.assertRaises(command_base.CommandError,
|
|
216
|
+
self.command._CheckInstancePreconditions,
|
|
217
|
+
[], [])
|
|
218
|
+
|
|
219
|
+
def testCheckInstancePreconditionsWithTooManyInstances(self):
|
|
220
|
+
for num_instances_to_mv in (101, 120, 200):
|
|
221
|
+
for num_instances_in_dest in (0, 10, 100, 101, 200):
|
|
222
|
+
instances_to_mv = self._GenerateInstanceResources(
|
|
223
|
+
num_instances_to_mv, prefix='i')
|
|
224
|
+
instances_in_dest = self._GenerateInstanceResources(
|
|
225
|
+
num_instances_in_dest, prefix='x')
|
|
226
|
+
self.assertRaises(
|
|
227
|
+
command_base.CommandError,
|
|
228
|
+
self.command._CheckInstancePreconditions,
|
|
229
|
+
instances_to_mv,
|
|
230
|
+
instances_in_dest)
|
|
231
|
+
|
|
232
|
+
def testCheckInstancePreconditionsWithNameCollisions(self):
|
|
233
|
+
# Tests with lots of collisions.
|
|
234
|
+
for num_instances in (1, 2, 10):
|
|
235
|
+
instances = self._GenerateInstanceResources(num_instances)
|
|
236
|
+
self.assertRaises(command_base.CommandError,
|
|
237
|
+
self.command._CheckInstancePreconditions,
|
|
238
|
+
instances, instances)
|
|
239
|
+
|
|
240
|
+
# Tests with only a single collision.
|
|
241
|
+
for num_instances in (1, 2, 10):
|
|
242
|
+
instances_to_mv = self._GenerateInstanceResources(
|
|
243
|
+
num_instances, prefix='i')
|
|
244
|
+
instances_in_dest = self._GenerateInstanceResources(
|
|
245
|
+
num_instances, prefix='x')
|
|
246
|
+
instances_in_dest.extend(self._GenerateInstanceResources(1, prefix='i'))
|
|
247
|
+
self.assertRaises(
|
|
248
|
+
command_base.CommandError,
|
|
249
|
+
self.command._CheckInstancePreconditions,
|
|
250
|
+
instances_to_mv,
|
|
251
|
+
instances_in_dest)
|
|
252
|
+
|
|
253
|
+
def testCheckInstancePreconditionsUnderNormalConditions(self):
|
|
254
|
+
for num_instances_to_mv in (1, 2, 10):
|
|
255
|
+
for num_instances_in_dest in (0, 2, 10):
|
|
256
|
+
instances_to_mv = self._GenerateInstanceResources(
|
|
257
|
+
num_instances_to_mv, prefix='i')
|
|
258
|
+
instances_in_dest = self._GenerateInstanceResources(
|
|
259
|
+
num_instances_in_dest, prefix='x')
|
|
260
|
+
self.command._CheckInstancePreconditions(
|
|
261
|
+
instances_to_mv, instances_in_dest)
|
|
262
|
+
|
|
263
|
+
def testCheckDiskPreconditionsWithTooManyDisks(self):
|
|
264
|
+
for num_disks in (101, 120, 200):
|
|
265
|
+
disk_names = ['disk-%s' % i for i in xrange(num_disks)]
|
|
266
|
+
self.assertRaises(
|
|
267
|
+
command_base.CommandError,
|
|
268
|
+
self.command._CheckDiskPreconditions,
|
|
269
|
+
[],
|
|
270
|
+
disk_names)
|
|
271
|
+
|
|
272
|
+
def testCheckDiskPreconditionsWithPoorDiskAttachment(self):
|
|
273
|
+
for num_instances in (1, 2, 10):
|
|
274
|
+
for num_disks in xrange(1, num_instances + 1):
|
|
275
|
+
self.assertRaises(
|
|
276
|
+
command_base.CommandError,
|
|
277
|
+
self.command._CheckDiskPreconditions,
|
|
278
|
+
self._GenerateInstanceResources(num_instances, prefix='i'),
|
|
279
|
+
['i-%s' % i for i in xrange(num_disks)])
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
class ResumeMoveTest(MoveInstancesBaseTestCase):
|
|
283
|
+
|
|
284
|
+
def _CreateCommand(self):
|
|
285
|
+
return move_cmds.ResumeMove('resumemove', self.flag_values)
|
|
286
|
+
|
|
287
|
+
def testGetKeyWithGoodKeys(self):
|
|
288
|
+
test_cases = (
|
|
289
|
+
({'key1': []}, 'key1', []),
|
|
290
|
+
({'key1': [1, 2, 3]}, 'key1', [1, 2, 3]),
|
|
291
|
+
({'key1': [1, 2, 3], 'key2': 5}, 'key2', 5))
|
|
292
|
+
for log, key, expected in test_cases:
|
|
293
|
+
self.assertEqual(self.command._GetKey(log, key), expected)
|
|
294
|
+
|
|
295
|
+
def testGetKeyWithBadKeys(self):
|
|
296
|
+
test_cases = (
|
|
297
|
+
{},
|
|
298
|
+
{'key1': []},
|
|
299
|
+
{'key1': [1, 2, 3]},
|
|
300
|
+
{'key1': [1, 2, 3], 'key2': 5})
|
|
301
|
+
for log in test_cases:
|
|
302
|
+
self.assertRaises(command_base.CommandError,
|
|
303
|
+
self.command._GetKey, log, 'nonexistent')
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
if __name__ == '__main__':
|
|
307
|
+
unittest.main()
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Copyright 2012 Google Inc. All Rights Reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
"""Commands for interacting with Google Compute Engine VM networks."""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
from google.apputils import appcommands
|
|
22
|
+
import gflags as flags
|
|
23
|
+
|
|
24
|
+
from gcutil import command_base
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
FLAGS = flags.FLAGS
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class NetworkCommand(command_base.GoogleComputeCommand):
|
|
31
|
+
"""Base command for working with the networks collection."""
|
|
32
|
+
|
|
33
|
+
default_sort_field = 'name'
|
|
34
|
+
summary_fields = (('name', 'name'),
|
|
35
|
+
('description', 'description'),
|
|
36
|
+
('addresses', 'IPv4Range'),
|
|
37
|
+
('gateway', 'gatewayIPv4'))
|
|
38
|
+
|
|
39
|
+
detail_fields = (('name', 'name'),
|
|
40
|
+
('description', 'description'),
|
|
41
|
+
('creation-time', 'creationTimestamp'),
|
|
42
|
+
('addresses', 'IPv4Range'),
|
|
43
|
+
('gateway', 'gatewayIPv4'))
|
|
44
|
+
|
|
45
|
+
resource_collection_name = 'networks'
|
|
46
|
+
|
|
47
|
+
def __init__(self, name, flag_values):
|
|
48
|
+
super(NetworkCommand, self).__init__(name, flag_values)
|
|
49
|
+
|
|
50
|
+
def SetApi(self, api):
|
|
51
|
+
"""Set the Google Compute Engine API for the command.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
api: The Google Compute Engine API used by this command.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
None.
|
|
58
|
+
|
|
59
|
+
"""
|
|
60
|
+
self._networks_api = api.networks()
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class AddNetwork(NetworkCommand):
|
|
64
|
+
"""Create a new network instance."""
|
|
65
|
+
|
|
66
|
+
positional_args = '<network-name>'
|
|
67
|
+
|
|
68
|
+
def __init__(self, name, flag_values):
|
|
69
|
+
super(AddNetwork, self).__init__(name, flag_values)
|
|
70
|
+
|
|
71
|
+
flags.DEFINE_string('description',
|
|
72
|
+
'',
|
|
73
|
+
'Network description.',
|
|
74
|
+
flag_values=flag_values)
|
|
75
|
+
flags.DEFINE_string('range',
|
|
76
|
+
'10.0.0.0/8',
|
|
77
|
+
'IPv4 address range of this network.',
|
|
78
|
+
flag_values=flag_values)
|
|
79
|
+
flags.DEFINE_string('gateway',
|
|
80
|
+
'10.0.0.1',
|
|
81
|
+
'IPv4 address of the gateway within the network.',
|
|
82
|
+
flag_values=flag_values)
|
|
83
|
+
flags.DEFINE_list('reserve',
|
|
84
|
+
[],
|
|
85
|
+
'IPv4 addresses on the network which should not be '
|
|
86
|
+
'automatically assigned (comma separated).',
|
|
87
|
+
flag_values=flag_values)
|
|
88
|
+
|
|
89
|
+
def Handle(self, network_name):
|
|
90
|
+
"""Add the specified network.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
network_name: The name of the network to add.
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
The result of adding the network.
|
|
97
|
+
"""
|
|
98
|
+
network_resource = {
|
|
99
|
+
'kind': self._GetResourceApiKind('network'),
|
|
100
|
+
'name': self.DenormalizeResourceName(network_name),
|
|
101
|
+
'description': self._flags.description,
|
|
102
|
+
'IPv4Range': self._flags.range,
|
|
103
|
+
'gatewayIPv4': self._flags.gateway,
|
|
104
|
+
'reservedIPv4': self._flags.reserve,
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
network_request = self._networks_api.insert(project=self._project,
|
|
108
|
+
body=network_resource)
|
|
109
|
+
return network_request.execute()
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class GetNetwork(NetworkCommand):
|
|
113
|
+
"""Get a network instance."""
|
|
114
|
+
|
|
115
|
+
positional_args = '<network-name>'
|
|
116
|
+
|
|
117
|
+
def __init__(self, name, flag_values):
|
|
118
|
+
super(GetNetwork, self).__init__(name, flag_values)
|
|
119
|
+
|
|
120
|
+
def Handle(self, network_name):
|
|
121
|
+
"""Get the specified network.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
network_name: The name of the network to get.
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
The result of getting the network.
|
|
128
|
+
"""
|
|
129
|
+
network_request = self._networks_api.get(
|
|
130
|
+
project=self._project,
|
|
131
|
+
network=self.DenormalizeResourceName(network_name))
|
|
132
|
+
|
|
133
|
+
return network_request.execute()
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class DeleteNetwork(NetworkCommand):
|
|
137
|
+
"""Delete one or more machine networks.
|
|
138
|
+
|
|
139
|
+
If multiple network names are specified, the networks will be deleted in
|
|
140
|
+
parallel.
|
|
141
|
+
"""
|
|
142
|
+
|
|
143
|
+
positional_args = '<network-name-1> ... <network-name-n>'
|
|
144
|
+
safety_prompt = 'Delete network'
|
|
145
|
+
|
|
146
|
+
def __init__(self, name, flag_values):
|
|
147
|
+
super(DeleteNetwork, self).__init__(name, flag_values)
|
|
148
|
+
|
|
149
|
+
def Handle(self, *network_names):
|
|
150
|
+
"""Delete the specified networks.
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
*network_names: The names of the networks to delete.
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
Tuple (results, exceptions) - results of deleting the networks.
|
|
157
|
+
"""
|
|
158
|
+
requests = []
|
|
159
|
+
for name in network_names:
|
|
160
|
+
requests.append(self._networks_api.delete(
|
|
161
|
+
project=self._project,
|
|
162
|
+
network=self.DenormalizeResourceName(name)))
|
|
163
|
+
results, exceptions = self.ExecuteRequests(requests)
|
|
164
|
+
return self.MakeListResult(results, 'operationList'), exceptions
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
class ListNetworks(NetworkCommand, command_base.GoogleComputeListCommand):
|
|
168
|
+
"""List the networks for a project."""
|
|
169
|
+
|
|
170
|
+
def ListFunc(self):
|
|
171
|
+
return self._networks_api.list
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def AddCommands():
|
|
175
|
+
appcommands.AddCmd('addnetwork', AddNetwork)
|
|
176
|
+
appcommands.AddCmd('getnetwork', GetNetwork)
|
|
177
|
+
appcommands.AddCmd('deletenetwork', DeleteNetwork)
|
|
178
|
+
appcommands.AddCmd('listnetworks', ListNetworks)
|