/BRI_RNAseq_Nextera_minus_trinity_optimized/pymodules/python2.7/lib/python/apache_libcloud-0.15.1-py2.7.egg/libcloud/compute/drivers/softlayer.py
Python | 474 lines | 391 code | 50 blank | 33 comment | 16 complexity | c66b58049a1717e8ef891acfafe36730 MD5 | raw file
1# Licensed to the Apache Software Foundation (ASF) under one or more
2# contributor license agreements. See the NOTICE file distributed with
3# this work for additional information regarding copyright ownership.
4# The ASF licenses this file to You under the Apache License, Version 2.0
5# (the "License"); you may not use this file except in compliance with
6# the License. You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15"""
16Softlayer driver
17"""
18
19import time
20
21from libcloud.common.base import ConnectionUserAndKey
22from libcloud.common.xmlrpc import XMLRPCResponse, XMLRPCConnection
23from libcloud.common.types import InvalidCredsError, LibcloudError
24from libcloud.compute.types import Provider, NodeState
25from libcloud.compute.base import NodeDriver, Node, NodeLocation, NodeSize, \
26 NodeImage
27
28DEFAULT_DOMAIN = 'example.com'
29DEFAULT_CPU_SIZE = 1
30DEFAULT_RAM_SIZE = 2048
31DEFAULT_DISK_SIZE = 100
32
33DATACENTERS = {
34 'hou02': {'country': 'US'},
35 'sea01': {'country': 'US', 'name': 'Seattle - West Coast U.S.'},
36 'wdc01': {'country': 'US', 'name': 'Washington, DC - East Coast U.S.'},
37 'dal01': {'country': 'US'},
38 'dal02': {'country': 'US'},
39 'dal04': {'country': 'US'},
40 'dal05': {'country': 'US', 'name': 'Dallas - Central U.S.'},
41 'dal06': {'country': 'US'},
42 'dal07': {'country': 'US'},
43 'sjc01': {'country': 'US', 'name': 'San Jose - West Coast U.S.'},
44 'sng01': {'country': 'SG', 'name': 'Singapore - Southeast Asia'},
45 'ams01': {'country': 'NL', 'name': 'Amsterdam - Western Europe'},
46}
47
48NODE_STATE_MAP = {
49 'RUNNING': NodeState.RUNNING,
50 'HALTED': NodeState.UNKNOWN,
51 'PAUSED': NodeState.UNKNOWN,
52 'INITIATING': NodeState.PENDING
53}
54
55SL_BASE_TEMPLATES = [
56 {
57 'name': '1 CPU, 1GB ram, 25GB',
58 'ram': 1024,
59 'disk': 25,
60 'cpus': 1,
61 }, {
62 'name': '1 CPU, 1GB ram, 100GB',
63 'ram': 1024,
64 'disk': 100,
65 'cpus': 1,
66 }, {
67 'name': '1 CPU, 2GB ram, 100GB',
68 'ram': 2 * 1024,
69 'disk': 100,
70 'cpus': 1,
71 }, {
72 'name': '1 CPU, 4GB ram, 100GB',
73 'ram': 4 * 1024,
74 'disk': 100,
75 'cpus': 1,
76 }, {
77 'name': '2 CPU, 2GB ram, 100GB',
78 'ram': 2 * 1024,
79 'disk': 100,
80 'cpus': 2,
81 }, {
82 'name': '2 CPU, 4GB ram, 100GB',
83 'ram': 4 * 1024,
84 'disk': 100,
85 'cpus': 2,
86 }, {
87 'name': '2 CPU, 8GB ram, 100GB',
88 'ram': 8 * 1024,
89 'disk': 100,
90 'cpus': 2,
91 }, {
92 'name': '4 CPU, 4GB ram, 100GB',
93 'ram': 4 * 1024,
94 'disk': 100,
95 'cpus': 4,
96 }, {
97 'name': '4 CPU, 8GB ram, 100GB',
98 'ram': 8 * 1024,
99 'disk': 100,
100 'cpus': 4,
101 }, {
102 'name': '6 CPU, 4GB ram, 100GB',
103 'ram': 4 * 1024,
104 'disk': 100,
105 'cpus': 6,
106 }, {
107 'name': '6 CPU, 8GB ram, 100GB',
108 'ram': 8 * 1024,
109 'disk': 100,
110 'cpus': 6,
111 }, {
112 'name': '8 CPU, 8GB ram, 100GB',
113 'ram': 8 * 1024,
114 'disk': 100,
115 'cpus': 8,
116 }, {
117 'name': '8 CPU, 16GB ram, 100GB',
118 'ram': 16 * 1024,
119 'disk': 100,
120 'cpus': 8,
121 }]
122
123SL_TEMPLATES = {}
124for i, template in enumerate(SL_BASE_TEMPLATES):
125 # Add local disk templates
126 local = template.copy()
127 local['local_disk'] = True
128 SL_TEMPLATES[i] = local
129
130
131class SoftLayerException(LibcloudError):
132 """
133 Exception class for SoftLayer driver
134 """
135 pass
136
137
138class SoftLayerResponse(XMLRPCResponse):
139 defaultExceptionCls = SoftLayerException
140 exceptions = {
141 'SoftLayer_Account': InvalidCredsError,
142 }
143
144
145class SoftLayerConnection(XMLRPCConnection, ConnectionUserAndKey):
146 responseCls = SoftLayerResponse
147 host = 'api.softlayer.com'
148 endpoint = '/xmlrpc/v3'
149
150 def request(self, service, method, *args, **kwargs):
151 headers = {}
152 headers.update(self._get_auth_headers())
153 headers.update(self._get_init_params(service, kwargs.get('id')))
154 headers.update(
155 self._get_object_mask(service, kwargs.get('object_mask')))
156 headers.update(
157 self._get_object_mask(service, kwargs.get('object_mask')))
158
159 args = ({'headers': headers}, ) + args
160 endpoint = '%s/%s' % (self.endpoint, service)
161
162 return super(SoftLayerConnection, self).request(method, *args,
163 **{'endpoint':
164 endpoint})
165
166 def _get_auth_headers(self):
167 return {
168 'authenticate': {
169 'username': self.user_id,
170 'apiKey': self.key
171 }
172 }
173
174 def _get_init_params(self, service, id):
175 if id is not None:
176 return {
177 '%sInitParameters' % service: {'id': id}
178 }
179 else:
180 return {}
181
182 def _get_object_mask(self, service, mask):
183 if mask is not None:
184 return {
185 '%sObjectMask' % service: {'mask': mask}
186 }
187 else:
188 return {}
189
190
191class SoftLayerNodeDriver(NodeDriver):
192 """
193 SoftLayer node driver
194
195 Extra node attributes:
196 - password: root password
197 - hourlyRecurringFee: hourly price (if applicable)
198 - recurringFee : flat rate (if applicable)
199 - recurringMonths : The number of months in which the recurringFee
200 will be incurred.
201 """
202 connectionCls = SoftLayerConnection
203 name = 'SoftLayer'
204 website = 'http://www.softlayer.com/'
205 type = Provider.SOFTLAYER
206
207 features = {'create_node': ['generates_password']}
208
209 def _to_node(self, host):
210 try:
211 password = \
212 host['operatingSystem']['passwords'][0]['password']
213 except (IndexError, KeyError):
214 password = None
215
216 hourlyRecurringFee = host.get('billingItem', {}).get(
217 'hourlyRecurringFee', 0)
218 recurringFee = host.get('billingItem', {}).get('recurringFee', 0)
219 recurringMonths = host.get('billingItem', {}).get('recurringMonths', 0)
220 createDate = host.get('createDate', None)
221
222 # When machine is launching it gets state halted
223 # we change this to pending
224 state = NODE_STATE_MAP.get(host['powerState']['keyName'],
225 NodeState.UNKNOWN)
226
227 if not password and state == NodeState.UNKNOWN:
228 state = NODE_STATE_MAP['INITIATING']
229
230 public_ips = []
231 private_ips = []
232
233 if 'primaryIpAddress' in host:
234 public_ips.append(host['primaryIpAddress'])
235
236 if 'primaryBackendIpAddress' in host:
237 private_ips.append(host['primaryBackendIpAddress'])
238
239 image = host.get('operatingSystem', {}).get('softwareLicense', {}) \
240 .get('softwareDescription', {}) \
241 .get('longDescription', None)
242
243 return Node(
244 id=host['id'],
245 name=host['fullyQualifiedDomainName'],
246 state=state,
247 public_ips=public_ips,
248 private_ips=private_ips,
249 driver=self,
250 extra={
251 'hostname': host['hostname'],
252 'fullyQualifiedDomainName': host['fullyQualifiedDomainName'],
253 'password': password,
254 'maxCpu': host.get('maxCpu', None),
255 'datacenter': host.get('datacenter', {}).get('longName', None),
256 'maxMemory': host.get('maxMemory', None),
257 'image': image,
258 'hourlyRecurringFee': hourlyRecurringFee,
259 'recurringFee': recurringFee,
260 'recurringMonths': recurringMonths,
261 'created': createDate,
262 }
263 )
264
265 def destroy_node(self, node):
266 self.connection.request(
267 'SoftLayer_Virtual_Guest', 'deleteObject', id=node.id
268 )
269 return True
270
271 def reboot_node(self, node):
272 self.connection.request(
273 'SoftLayer_Virtual_Guest', 'rebootSoft', id=node.id
274 )
275 return True
276
277 def ex_stop_node(self, node):
278 self.connection.request(
279 'SoftLayer_Virtual_Guest', 'powerOff', id=node.id
280 )
281 return True
282
283 def ex_start_node(self, node):
284 self.connection.request(
285 'SoftLayer_Virtual_Guest', 'powerOn', id=node.id
286 )
287 return True
288
289 def _get_order_information(self, node_id, timeout=1200, check_interval=5):
290 mask = {
291 'billingItem': '',
292 'powerState': '',
293 'operatingSystem': {'passwords': ''},
294 'provisionDate': '',
295 }
296
297 for i in range(0, timeout, check_interval):
298 res = self.connection.request(
299 'SoftLayer_Virtual_Guest',
300 'getObject',
301 id=node_id,
302 object_mask=mask
303 ).object
304
305 if res.get('provisionDate', None):
306 return res
307
308 time.sleep(check_interval)
309
310 raise SoftLayerException('Timeout on getting node details')
311
312 def create_node(self, **kwargs):
313 """Create a new SoftLayer node
314
315 @inherits: :class:`NodeDriver.create_node`
316
317 :keyword ex_domain: e.g. libcloud.org
318 :type ex_domain: ``str``
319 :keyword ex_cpus: e.g. 2
320 :type ex_cpus: ``int``
321 :keyword ex_disk: e.g. 100
322 :type ex_disk: ``int``
323 :keyword ex_ram: e.g. 2048
324 :type ex_ram: ``int``
325 :keyword ex_bandwidth: e.g. 100
326 :type ex_bandwidth: ``int``
327 :keyword ex_local_disk: e.g. True
328 :type ex_local_disk: ``bool``
329 :keyword ex_datacenter: e.g. Dal05
330 :type ex_datacenter: ``str``
331 :keyword ex_os: e.g. UBUNTU_LATEST
332 :type ex_os: ``str``
333 """
334 name = kwargs['name']
335 os = 'DEBIAN_LATEST'
336 if 'ex_os' in kwargs:
337 os = kwargs['ex_os']
338 elif 'image' in kwargs:
339 os = kwargs['image'].id
340
341 size = kwargs.get('size', NodeSize(id=123, name='Custom', ram=None,
342 disk=None, bandwidth=None,
343 price=None,
344 driver=self.connection.driver))
345 ex_size_data = SL_TEMPLATES.get(int(size.id)) or {}
346 # plan keys are ints
347 cpu_count = kwargs.get('ex_cpus') or ex_size_data.get('cpus') or \
348 DEFAULT_CPU_SIZE
349 ram = kwargs.get('ex_ram') or ex_size_data.get('ram') or \
350 DEFAULT_RAM_SIZE
351 bandwidth = kwargs.get('ex_bandwidth') or size.bandwidth or 10
352 hourly = 'true' if kwargs.get('ex_hourly', True) else 'false'
353
354 local_disk = 'true'
355 if ex_size_data.get('local_disk') is False:
356 local_disk = 'false'
357
358 if kwargs.get('ex_local_disk') is False:
359 local_disk = 'false'
360
361 disk_size = DEFAULT_DISK_SIZE
362 if size.disk:
363 disk_size = size.disk
364 if kwargs.get('ex_disk'):
365 disk_size = kwargs.get('ex_disk')
366
367 datacenter = ''
368 if 'ex_datacenter' in kwargs:
369 datacenter = kwargs['ex_datacenter']
370 elif 'location' in kwargs:
371 datacenter = kwargs['location'].id
372
373 domain = kwargs.get('ex_domain')
374 if domain is None:
375 if name.find('.') != -1:
376 domain = name[name.find('.') + 1:]
377 if domain is None:
378 # TODO: domain is a required argument for the Sofylayer API, but it
379 # it shouldn't be.
380 domain = DEFAULT_DOMAIN
381
382 newCCI = {
383 'hostname': name,
384 'domain': domain,
385 'startCpus': cpu_count,
386 'maxMemory': ram,
387 'networkComponents': [{'maxSpeed': bandwidth}],
388 'hourlyBillingFlag': hourly,
389 'operatingSystemReferenceCode': os,
390 'localDiskFlag': local_disk,
391 'blockDevices': [
392 {
393 'device': '0',
394 'diskImage': {
395 'capacity': disk_size,
396 }
397 }
398 ]
399
400 }
401
402 if datacenter:
403 newCCI['datacenter'] = {'name': datacenter}
404
405 res = self.connection.request(
406 'SoftLayer_Virtual_Guest', 'createObject', newCCI
407 ).object
408
409 node_id = res['id']
410 raw_node = self._get_order_information(node_id)
411
412 return self._to_node(raw_node)
413
414 def _to_image(self, img):
415 return NodeImage(
416 id=img['template']['operatingSystemReferenceCode'],
417 name=img['itemPrice']['item']['description'],
418 driver=self.connection.driver
419 )
420
421 def list_images(self, location=None):
422 result = self.connection.request(
423 'SoftLayer_Virtual_Guest', 'getCreateObjectOptions'
424 ).object
425 return [self._to_image(i) for i in result['operatingSystems']]
426
427 def _to_size(self, id, size):
428 return NodeSize(
429 id=id,
430 name=size['name'],
431 ram=size['ram'],
432 disk=size['disk'],
433 bandwidth=size.get('bandwidth'),
434 price=None,
435 driver=self.connection.driver,
436 )
437
438 def list_sizes(self, location=None):
439 return [self._to_size(id, s) for id, s in SL_TEMPLATES.items()]
440
441 def _to_loc(self, loc):
442 country = 'UNKNOWN'
443 loc_id = loc['template']['datacenter']['name']
444 name = loc_id
445
446 if loc_id in DATACENTERS:
447 country = DATACENTERS[loc_id]['country']
448 name = DATACENTERS[loc_id].get('name', loc_id)
449 return NodeLocation(id=loc_id, name=name,
450 country=country, driver=self)
451
452 def list_locations(self):
453 res = self.connection.request(
454 'SoftLayer_Virtual_Guest', 'getCreateObjectOptions'
455 ).object
456 return [self._to_loc(l) for l in res['datacenters']]
457
458 def list_nodes(self):
459 mask = {
460 'virtualGuests': {
461 'powerState': '',
462 'hostname': '',
463 'maxMemory': '',
464 'datacenter': '',
465 'operatingSystem': {'passwords': ''},
466 'billingItem': '',
467 },
468 }
469 res = self.connection.request(
470 "SoftLayer_Account",
471 "getVirtualGuests",
472 object_mask=mask
473 ).object
474 return [self._to_node(h) for h in res]