2
0

services.py 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199
  1. """
  2. Services implemented by the OpenStack provider.
  3. """
  4. import logging
  5. from cinderclient.exceptions import NotFound as CinderNotFound
  6. from neutronclient.common.exceptions import NeutronClientException
  7. from neutronclient.common.exceptions import PortNotFoundClient
  8. from novaclient.exceptions import NotFound as NovaNotFound
  9. from openstack.exceptions import HttpException
  10. from openstack.exceptions import NotFoundException
  11. from openstack.exceptions import ResourceNotFound
  12. from swiftclient import ClientException as SwiftClientException
  13. import cloudbridge.cloud.base.helpers as cb_helpers
  14. from cloudbridge.cloud.base.middleware import dispatch
  15. from cloudbridge.cloud.base.resources import BaseLaunchConfig
  16. from cloudbridge.cloud.base.resources import ClientPagedResultList
  17. from cloudbridge.cloud.base.services import BaseBucketObjectService
  18. from cloudbridge.cloud.base.services import BaseBucketService
  19. from cloudbridge.cloud.base.services import BaseComputeService
  20. from cloudbridge.cloud.base.services import BaseFloatingIPService
  21. from cloudbridge.cloud.base.services import BaseGatewayService
  22. from cloudbridge.cloud.base.services import BaseImageService
  23. from cloudbridge.cloud.base.services import BaseInstanceService
  24. from cloudbridge.cloud.base.services import BaseKeyPairService
  25. from cloudbridge.cloud.base.services import BaseNetworkService
  26. from cloudbridge.cloud.base.services import BaseNetworkingService
  27. from cloudbridge.cloud.base.services import BaseRegionService
  28. from cloudbridge.cloud.base.services import BaseRouterService
  29. from cloudbridge.cloud.base.services import BaseSecurityService
  30. from cloudbridge.cloud.base.services import BaseSnapshotService
  31. from cloudbridge.cloud.base.services import BaseStorageService
  32. from cloudbridge.cloud.base.services import BaseSubnetService
  33. from cloudbridge.cloud.base.services import BaseVMFirewallRuleService
  34. from cloudbridge.cloud.base.services import BaseVMFirewallService
  35. from cloudbridge.cloud.base.services import BaseVMTypeService
  36. from cloudbridge.cloud.base.services import BaseVolumeService
  37. from cloudbridge.cloud.interfaces.exceptions \
  38. import DuplicateResourceException
  39. from cloudbridge.cloud.interfaces.exceptions import InvalidParamException
  40. from cloudbridge.cloud.interfaces.exceptions import InvalidValueException
  41. from cloudbridge.cloud.interfaces.resources import KeyPair
  42. from cloudbridge.cloud.interfaces.resources import MachineImage
  43. from cloudbridge.cloud.interfaces.resources import Network
  44. from cloudbridge.cloud.interfaces.resources import PlacementZone
  45. from cloudbridge.cloud.interfaces.resources import Snapshot
  46. from cloudbridge.cloud.interfaces.resources import Subnet
  47. from cloudbridge.cloud.interfaces.resources import TrafficDirection
  48. from cloudbridge.cloud.interfaces.resources import VMFirewall
  49. from cloudbridge.cloud.interfaces.resources import VMType
  50. from cloudbridge.cloud.interfaces.resources import Volume
  51. from . import helpers as oshelpers
  52. from .resources import OpenStackBucket
  53. from .resources import OpenStackBucketObject
  54. from .resources import OpenStackFloatingIP
  55. from .resources import OpenStackInstance
  56. from .resources import OpenStackInternetGateway
  57. from .resources import OpenStackKeyPair
  58. from .resources import OpenStackMachineImage
  59. from .resources import OpenStackNetwork
  60. from .resources import OpenStackRegion
  61. from .resources import OpenStackRouter
  62. from .resources import OpenStackSnapshot
  63. from .resources import OpenStackSubnet
  64. from .resources import OpenStackVMFirewall
  65. from .resources import OpenStackVMFirewallRule
  66. from .resources import OpenStackVMType
  67. from .resources import OpenStackVolume
  68. log = logging.getLogger(__name__)
  69. class OpenStackSecurityService(BaseSecurityService):
  70. def __init__(self, provider):
  71. super(OpenStackSecurityService, self).__init__(provider)
  72. # Initialize provider services
  73. self._key_pairs = OpenStackKeyPairService(provider)
  74. self._vm_firewalls = OpenStackVMFirewallService(provider)
  75. self._vm_firewall_rules = OpenStackVMFirewallRuleService(provider)
  76. def get_or_create_ec2_credentials(self):
  77. """
  78. A provider specific method than returns the ec2 credentials for the
  79. current user, or creates a new pair if one doesn't exist.
  80. """
  81. keystone = self.provider.keystone
  82. if hasattr(keystone, 'ec2'):
  83. user_id = keystone.session.get_user_id()
  84. user_creds = [cred for cred in keystone.ec2.list(user_id) if
  85. cred.tenant_id == keystone.session.get_project_id()]
  86. if user_creds:
  87. return user_creds[0]
  88. else:
  89. return keystone.ec2.create(
  90. user_id, keystone.session.get_project_id())
  91. return None
  92. def get_ec2_endpoints(self):
  93. """
  94. A provider specific method than returns the ec2 endpoints if
  95. available.
  96. """
  97. keystone = self.provider.keystone
  98. ec2_url = keystone.session.get_endpoint(service_type='ec2')
  99. s3_url = keystone.session.get_endpoint(service_type='s3')
  100. return {'ec2_endpoint': ec2_url,
  101. 's3_endpoint': s3_url}
  102. class OpenStackKeyPairService(BaseKeyPairService):
  103. def __init__(self, provider):
  104. super(OpenStackKeyPairService, self).__init__(provider)
  105. @dispatch(event="provider.security.key_pairs.get",
  106. priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
  107. def get(self, key_pair_id):
  108. """
  109. Returns a KeyPair given its id.
  110. """
  111. log.debug("Returning KeyPair with the id %s", key_pair_id)
  112. try:
  113. return OpenStackKeyPair(
  114. self.provider, self.provider.nova.keypairs.get(key_pair_id))
  115. except NovaNotFound:
  116. log.debug("KeyPair %s was not found.", key_pair_id)
  117. return None
  118. @dispatch(event="provider.security.key_pairs.list",
  119. priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
  120. def list(self, limit=None, marker=None):
  121. """
  122. List all key pairs associated with this account.
  123. :rtype: ``list`` of :class:`.KeyPair`
  124. :return: list of KeyPair objects
  125. """
  126. keypairs = self.provider.nova.keypairs.list()
  127. results = [OpenStackKeyPair(self.provider, kp)
  128. for kp in keypairs]
  129. log.debug("Listing all key pairs associated with OpenStack "
  130. "Account: %s", results)
  131. return ClientPagedResultList(self.provider, results,
  132. limit=limit, marker=marker)
  133. @dispatch(event="provider.security.key_pairs.find",
  134. priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
  135. def find(self, **kwargs):
  136. name = kwargs.pop('name', None)
  137. # All kwargs should have been popped at this time.
  138. if len(kwargs) > 0:
  139. raise InvalidParamException(
  140. "Unrecognised parameters for search: %s. Supported "
  141. "attributes: %s" % (kwargs, 'name'))
  142. keypairs = self.provider.nova.keypairs.findall(name=name)
  143. results = [OpenStackKeyPair(self.provider, kp)
  144. for kp in keypairs]
  145. log.debug("Searching for %s in: %s", name, keypairs)
  146. return ClientPagedResultList(self.provider, results)
  147. @dispatch(event="provider.security.key_pairs.create",
  148. priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
  149. def create(self, name, public_key_material=None):
  150. OpenStackKeyPair.assert_valid_resource_name(name)
  151. existing_kp = self.find(name=name)
  152. if existing_kp:
  153. raise DuplicateResourceException(
  154. 'Keypair already exists with name {0}'.format(name))
  155. private_key = None
  156. if not public_key_material:
  157. public_key_material, private_key = cb_helpers.generate_key_pair()
  158. kp = self.provider.nova.keypairs.create(name,
  159. public_key=public_key_material)
  160. cb_kp = OpenStackKeyPair(self.provider, kp)
  161. cb_kp.material = private_key
  162. return cb_kp
  163. @dispatch(event="provider.security.key_pairs.delete",
  164. priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
  165. def delete(self, kp):
  166. keypair = kp if isinstance(kp, OpenStackKeyPair) else self.get(kp)
  167. if keypair:
  168. # pylint:disable=protected-access
  169. keypair._key_pair.delete()
  170. class OpenStackVMFirewallService(BaseVMFirewallService):
  171. def __init__(self, provider):
  172. super(OpenStackVMFirewallService, self).__init__(provider)
  173. @dispatch(event="provider.security.vm_firewalls.get",
  174. priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
  175. def get(self, vm_firewall_id):
  176. try:
  177. return OpenStackVMFirewall(
  178. self.provider,
  179. self.provider.os_conn.network
  180. .get_security_group(vm_firewall_id))
  181. except (ResourceNotFound, NotFoundException):
  182. log.debug("Firewall %s not found.", vm_firewall_id)
  183. return None
  184. @dispatch(event="provider.security.vm_firewalls.list",
  185. priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
  186. def list(self, limit=None, marker=None):
  187. firewalls = [
  188. OpenStackVMFirewall(self.provider, fw)
  189. for fw in self.provider.os_conn.network.security_groups()]
  190. return ClientPagedResultList(self.provider, firewalls,
  191. limit=limit, marker=marker)
  192. @cb_helpers.deprecated_alias(network_id='network')
  193. @dispatch(event="provider.security.vm_firewalls.create",
  194. priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
  195. def create(self, label, network, description=None):
  196. OpenStackVMFirewall.assert_valid_resource_label(label)
  197. net = network.id if isinstance(network, Network) else network
  198. # We generally simulate a network being associated with a firewall
  199. # by storing the supplied value in the firewall description field that
  200. # is not modifiable after creation; however, because of some networking
  201. # specificity in Nectar, we must also allow an empty network id value.
  202. if not net:
  203. net = ""
  204. if not description:
  205. description = ""
  206. description += " [{}{}]".format(OpenStackVMFirewall._network_id_tag,
  207. net)
  208. sg = self.provider.os_conn.network.create_security_group(
  209. name=label, description=description)
  210. if sg:
  211. return OpenStackVMFirewall(self.provider, sg)
  212. return None
  213. @dispatch(event="provider.security.vm_firewalls.delete",
  214. priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
  215. def delete(self, vmf):
  216. fw = vmf if isinstance(vmf, OpenStackVMFirewall) else self.get(vmf)
  217. if fw:
  218. # pylint:disable=protected-access
  219. fw._vm_firewall.delete(self.provider.os_conn.session)
  220. class OpenStackVMFirewallRuleService(BaseVMFirewallRuleService):
  221. def __init__(self, provider, firewall):
  222. super(OpenStackVMFirewallRuleService, self).__init__(provider)
  223. def list(self, firewall, limit=None, marker=None):
  224. # pylint:disable=protected-access
  225. rules = [OpenStackVMFirewallRule(firewall, r)
  226. for r in firewall._vm_firewall.security_group_rules]
  227. return ClientPagedResultList(self.provider, rules,
  228. limit=limit, marker=marker)
  229. def create(self, firewall, direction, protocol=None, from_port=None,
  230. to_port=None, cidr=None, src_dest_fw=None):
  231. src_dest_fw_id = (src_dest_fw.id if isinstance(src_dest_fw,
  232. OpenStackVMFirewall)
  233. else src_dest_fw)
  234. try:
  235. if direction == TrafficDirection.INBOUND:
  236. os_direction = 'ingress'
  237. elif direction == TrafficDirection.OUTBOUND:
  238. os_direction = 'egress'
  239. else:
  240. raise InvalidValueException("direction", direction)
  241. # pylint:disable=protected-access
  242. rule = self.provider.os_conn.network.create_security_group_rule(
  243. security_group_id=firewall.id,
  244. direction=os_direction,
  245. port_range_max=to_port,
  246. port_range_min=from_port,
  247. protocol=protocol,
  248. remote_ip_prefix=cidr,
  249. remote_group_id=src_dest_fw_id)
  250. firewall.refresh()
  251. return OpenStackVMFirewallRule(firewall, rule.to_dict())
  252. except HttpException as e:
  253. firewall.refresh()
  254. # 409=Conflict, raised for duplicate rule
  255. if e.status_code == 409:
  256. existing = self.find(direction=direction, protocol=protocol,
  257. from_port=from_port, to_port=to_port,
  258. cidr=cidr, src_dest_fw_id=src_dest_fw_id)
  259. return existing[0]
  260. else:
  261. raise e
  262. def delete(self, firewall, rule):
  263. self.provider.os_conn.network.delete_security_group_rule(rule.id)
  264. firewall.refresh()
  265. class OpenStackStorageService(BaseStorageService):
  266. def __init__(self, provider):
  267. super(OpenStackStorageService, self).__init__(provider)
  268. # Initialize provider services
  269. self._volume_svc = OpenStackVolumeService(self.provider)
  270. self._snapshot_svc = OpenStackSnapshotService(self.provider)
  271. self._bucket_svc = OpenStackBucketService(self.provider)
  272. self._bucket_obj_svc = OpenStackBucketObjectService(self.provider)
  273. @property
  274. def volumes(self):
  275. return self._volume_svc
  276. @property
  277. def snapshots(self):
  278. return self._snapshot_svc
  279. @property
  280. def buckets(self):
  281. return self._bucket_svc
  282. @property
  283. def _bucket_objects(self):
  284. return self._bucket_obj_svc
  285. class OpenStackVolumeService(BaseVolumeService):
  286. def __init__(self, provider):
  287. super(OpenStackVolumeService, self).__init__(provider)
  288. @dispatch(event="provider.storage.volumes.get",
  289. priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
  290. def get(self, volume_id):
  291. try:
  292. return OpenStackVolume(
  293. self.provider, self.provider.cinder.volumes.get(volume_id))
  294. except CinderNotFound:
  295. log.debug("Volume %s was not found.", volume_id)
  296. return None
  297. @dispatch(event="provider.storage.volumes.find",
  298. priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
  299. def find(self, **kwargs):
  300. label = kwargs.pop('label', None)
  301. # All kwargs should have been popped at this time.
  302. if len(kwargs) > 0:
  303. raise InvalidParamException(
  304. "Unrecognised parameters for search: %s. Supported "
  305. "attributes: %s" % (kwargs, 'label'))
  306. log.debug("Searching for an OpenStack Volume with the label %s", label)
  307. search_opts = {'name': label}
  308. cb_vols = [
  309. OpenStackVolume(self.provider, vol)
  310. for vol in self.provider.cinder.volumes.list(
  311. search_opts=search_opts,
  312. limit=oshelpers.os_result_limit(self.provider),
  313. marker=None)]
  314. return oshelpers.to_server_paged_list(self.provider, cb_vols)
  315. @dispatch(event="provider.storage.volumes.list",
  316. priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
  317. def list(self, limit=None, marker=None):
  318. cb_vols = [
  319. OpenStackVolume(self.provider, vol)
  320. for vol in self.provider.cinder.volumes.list(
  321. limit=oshelpers.os_result_limit(self.provider, limit),
  322. marker=marker)]
  323. return oshelpers.to_server_paged_list(self.provider, cb_vols, limit)
  324. @dispatch(event="provider.storage.volumes.create",
  325. priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
  326. def create(self, label, size, zone, snapshot=None, description=None):
  327. OpenStackVolume.assert_valid_resource_label(label)
  328. zone_id = zone.id if isinstance(zone, PlacementZone) else zone
  329. snapshot_id = snapshot.id if isinstance(
  330. snapshot, OpenStackSnapshot) and snapshot else snapshot
  331. os_vol = self.provider.cinder.volumes.create(
  332. size, name=label, description=description,
  333. availability_zone=zone_id, snapshot_id=snapshot_id)
  334. return OpenStackVolume(self.provider, os_vol)
  335. @dispatch(event="provider.storage.volumes.delete",
  336. priority=BaseVolumeService.STANDARD_EVENT_PRIORITY)
  337. def delete(self, vol):
  338. volume = vol if isinstance(vol, OpenStackVolume) else self.get(vol)
  339. if volume:
  340. # pylint:disable=protected-access
  341. volume._volume.delete()
  342. class OpenStackSnapshotService(BaseSnapshotService):
  343. def __init__(self, provider):
  344. super(OpenStackSnapshotService, self).__init__(provider)
  345. @dispatch(event="provider.storage.snapshots.get",
  346. priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
  347. def get(self, snapshot_id):
  348. try:
  349. return OpenStackSnapshot(
  350. self.provider,
  351. self.provider.cinder.volume_snapshots.get(snapshot_id))
  352. except CinderNotFound:
  353. log.debug("Snapshot %s was not found.", snapshot_id)
  354. return None
  355. @dispatch(event="provider.storage.snapshots.find",
  356. priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
  357. def find(self, **kwargs):
  358. label = kwargs.pop('label', None)
  359. # All kwargs should have been popped at this time.
  360. if len(kwargs) > 0:
  361. raise InvalidParamException(
  362. "Unrecognised parameters for search: %s. Supported "
  363. "attributes: %s" % (kwargs, 'label'))
  364. search_opts = {'name': label, # TODO: Cinder is ignoring name
  365. 'limit': oshelpers.os_result_limit(self.provider),
  366. 'marker': None}
  367. log.debug("Searching for an OpenStack snapshot with the following "
  368. "params: %s", search_opts)
  369. cb_snaps = [
  370. OpenStackSnapshot(self.provider, snap) for
  371. snap in self.provider.cinder.volume_snapshots.list(search_opts)
  372. if snap.name == label]
  373. return oshelpers.to_server_paged_list(self.provider, cb_snaps)
  374. @dispatch(event="provider.storage.snapshots.list",
  375. priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
  376. def list(self, limit=None, marker=None):
  377. cb_snaps = [
  378. OpenStackSnapshot(self.provider, snap) for
  379. snap in self.provider.cinder.volume_snapshots.list(
  380. search_opts={'limit': oshelpers.os_result_limit(self.provider,
  381. limit),
  382. 'marker': marker})]
  383. return oshelpers.to_server_paged_list(self.provider, cb_snaps, limit)
  384. @dispatch(event="provider.storage.snapshots.create",
  385. priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
  386. def create(self, label, volume, description=None):
  387. OpenStackSnapshot.assert_valid_resource_label(label)
  388. volume_id = (volume.id if isinstance(volume, OpenStackVolume)
  389. else volume)
  390. os_snap = self.provider.cinder.volume_snapshots.create(
  391. volume_id, name=label,
  392. description=description)
  393. return OpenStackSnapshot(self.provider, os_snap)
  394. @dispatch(event="provider.storage.snapshots.delete",
  395. priority=BaseSnapshotService.STANDARD_EVENT_PRIORITY)
  396. def delete(self, snap):
  397. s = snap if isinstance(snap, OpenStackSnapshot) else self.get(snap)
  398. if s:
  399. # pylint:disable=protected-access
  400. s._snapshot.delete()
  401. class OpenStackBucketService(BaseBucketService):
  402. def __init__(self, provider):
  403. super(OpenStackBucketService, self).__init__(provider)
  404. @dispatch(event="provider.storage.buckets.get",
  405. priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
  406. def get(self, bucket_id):
  407. """
  408. Returns a bucket given its ID. Returns ``None`` if the bucket
  409. does not exist.
  410. """
  411. _, container_list = self.provider.swift.get_account(
  412. prefix=bucket_id)
  413. if container_list:
  414. return OpenStackBucket(self.provider,
  415. next((c for c in container_list
  416. if c['name'] == bucket_id), None))
  417. else:
  418. log.debug("Bucket %s was not found.", bucket_id)
  419. return None
  420. @dispatch(event="provider.storage.buckets.find",
  421. priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
  422. def find(self, **kwargs):
  423. name = kwargs.pop('name', None)
  424. # All kwargs should have been popped at this time.
  425. if len(kwargs) > 0:
  426. raise InvalidParamException(
  427. "Unrecognised parameters for search: %s. Supported "
  428. "attributes: %s" % (kwargs, 'name'))
  429. _, container_list = self.provider.swift.get_account()
  430. cb_buckets = [OpenStackBucket(self.provider, c)
  431. for c in container_list
  432. if name in c.get("name")]
  433. return oshelpers.to_server_paged_list(self.provider, cb_buckets)
  434. @dispatch(event="provider.storage.buckets.list",
  435. priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
  436. def list(self, limit=None, marker=None):
  437. _, container_list = self.provider.swift.get_account(
  438. limit=oshelpers.os_result_limit(self.provider, limit),
  439. marker=marker)
  440. cb_buckets = [OpenStackBucket(self.provider, c)
  441. for c in container_list]
  442. return oshelpers.to_server_paged_list(self.provider, cb_buckets, limit)
  443. @dispatch(event="provider.storage.buckets.create",
  444. priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
  445. def create(self, name, location=None):
  446. OpenStackBucket.assert_valid_resource_name(name)
  447. location = location or self.provider.region_name
  448. try:
  449. self.provider.swift.head_container(name)
  450. raise DuplicateResourceException(
  451. 'Bucket already exists with name {0}'.format(name))
  452. except SwiftClientException:
  453. self.provider.swift.put_container(name)
  454. return self.get(name)
  455. @dispatch(event="provider.storage.buckets.delete",
  456. priority=BaseBucketService.STANDARD_EVENT_PRIORITY)
  457. def delete(self, bucket):
  458. b_id = bucket.id if isinstance(bucket, OpenStackBucket) else bucket
  459. self.provider.swift.delete_container(b_id)
  460. class OpenStackBucketObjectService(BaseBucketObjectService):
  461. def __init__(self, provider):
  462. super(OpenStackBucketObjectService, self).__init__(provider)
  463. def get(self, bucket, name):
  464. """
  465. Retrieve a given object from this bucket.
  466. """
  467. # Swift always returns a reference for the container first,
  468. # followed by a list containing references to objects.
  469. _, object_list = self.provider.swift.get_container(
  470. bucket.name, prefix=name)
  471. # Loop through list of objects looking for an exact name vs. a prefix
  472. for obj in object_list:
  473. if obj.get('name') == name:
  474. return OpenStackBucketObject(self.provider,
  475. bucket,
  476. obj)
  477. return None
  478. def list(self, bucket, limit=None, marker=None, prefix=None):
  479. """
  480. List all objects within this bucket.
  481. :rtype: BucketObject
  482. :return: List of all available BucketObjects within this bucket.
  483. """
  484. _, object_list = self.provider.swift.get_container(
  485. bucket.name,
  486. limit=oshelpers.os_result_limit(self.provider, limit),
  487. marker=marker, prefix=prefix)
  488. cb_objects = [OpenStackBucketObject(
  489. self.provider, bucket, obj) for obj in object_list]
  490. return oshelpers.to_server_paged_list(
  491. self.provider,
  492. cb_objects,
  493. limit)
  494. def find(self, bucket, **kwargs):
  495. _, obj_list = self.provider.swift.get_container(bucket.name)
  496. cb_objs = [OpenStackBucketObject(self.provider, bucket, obj)
  497. for obj in obj_list]
  498. filters = ['name']
  499. matches = cb_helpers.generic_find(filters, kwargs, cb_objs)
  500. return ClientPagedResultList(self.provider, list(matches))
  501. def create(self, bucket, object_name):
  502. self.provider.swift.put_object(bucket.name, object_name, None)
  503. return self.get(bucket, object_name)
  504. class OpenStackComputeService(BaseComputeService):
  505. def __init__(self, provider):
  506. super(OpenStackComputeService, self).__init__(provider)
  507. self._vm_type_svc = OpenStackVMTypeService(self.provider)
  508. self._instance_svc = OpenStackInstanceService(self.provider)
  509. self._region_svc = OpenStackRegionService(self.provider)
  510. self._images_svc = OpenStackImageService(self.provider)
  511. @property
  512. def images(self):
  513. return self._images_svc
  514. @property
  515. def vm_types(self):
  516. return self._vm_type_svc
  517. @property
  518. def instances(self):
  519. return self._instance_svc
  520. @property
  521. def regions(self):
  522. return self._region_svc
  523. class OpenStackImageService(BaseImageService):
  524. def __init__(self, provider):
  525. super(OpenStackImageService, self).__init__(provider)
  526. def get(self, image_id):
  527. """
  528. Returns an Image given its id
  529. """
  530. log.debug("Getting OpenStack Image with the id: %s", image_id)
  531. try:
  532. return OpenStackMachineImage(
  533. self.provider, self.provider.os_conn.image.get_image(image_id))
  534. except (NotFoundException, ResourceNotFound):
  535. log.debug("Image %s not found", image_id)
  536. return None
  537. def find(self, **kwargs):
  538. filters = ['label']
  539. obj_list = self
  540. return cb_helpers.generic_find(filters, kwargs, obj_list)
  541. def list(self, filter_by_owner=True, limit=None, marker=None):
  542. """
  543. List all images.
  544. """
  545. project_id = None
  546. if filter_by_owner:
  547. project_id = self.provider.os_conn.session.get_project_id()
  548. os_images = self.provider.os_conn.image.images(
  549. owner=project_id,
  550. limit=oshelpers.os_result_limit(self.provider, limit),
  551. marker=marker)
  552. cb_images = [
  553. OpenStackMachineImage(self.provider, img)
  554. for img in os_images]
  555. return oshelpers.to_server_paged_list(self.provider, cb_images, limit)
  556. class OpenStackInstanceService(BaseInstanceService):
  557. def __init__(self, provider):
  558. super(OpenStackInstanceService, self).__init__(provider)
  559. def _to_block_device_mapping(self, launch_config):
  560. """
  561. Extracts block device mapping information
  562. from a launch config and constructs a BlockDeviceMappingV2
  563. object.
  564. """
  565. bdm = []
  566. for device in launch_config.block_devices:
  567. bdm_dict = dict()
  568. if device.is_volume:
  569. bdm_dict['destination_type'] = 'volume'
  570. if device.is_root:
  571. bdm_dict['device_name'] = '/dev/sda'
  572. bdm_dict['boot_index'] = 0
  573. if isinstance(device.source, Snapshot):
  574. bdm_dict['source_type'] = 'snapshot'
  575. bdm_dict['uuid'] = device.source.id
  576. elif isinstance(device.source, Volume):
  577. bdm_dict['source_type'] = 'volume'
  578. bdm_dict['uuid'] = device.source.id
  579. elif isinstance(device.source, MachineImage):
  580. bdm_dict['source_type'] = 'image'
  581. bdm_dict['uuid'] = device.source.id
  582. else:
  583. bdm_dict['source_type'] = 'blank'
  584. if device.delete_on_terminate is not None:
  585. bdm_dict[
  586. 'delete_on_termination'] = device.delete_on_terminate
  587. if device.size:
  588. bdm_dict['volume_size'] = device.size
  589. else:
  590. bdm_dict['destination_type'] = 'local'
  591. bdm_dict['source_type'] = 'blank'
  592. bdm_dict['delete_on_termination'] = True
  593. bdm.append(bdm_dict)
  594. return bdm
  595. def _has_root_device(self, launch_config):
  596. if not launch_config:
  597. return False
  598. for device in launch_config.block_devices:
  599. if device.is_root:
  600. return True
  601. return False
  602. def create_launch_config(self):
  603. return BaseLaunchConfig(self.provider)
  604. @dispatch(event="provider.compute.instances.create",
  605. priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
  606. def create(self, label, image, vm_type, subnet, zone,
  607. key_pair=None, vm_firewalls=None, user_data=None,
  608. launch_config=None, **kwargs):
  609. OpenStackInstance.assert_valid_resource_label(label)
  610. image_id = image.id if isinstance(image, MachineImage) else image
  611. vm_size = vm_type.id if \
  612. isinstance(vm_type, VMType) else \
  613. self.provider.compute.vm_types.find(
  614. name=vm_type)[0].id
  615. if isinstance(subnet, Subnet):
  616. subnet_id = subnet.id
  617. net_id = subnet.network_id
  618. else:
  619. subnet_id = subnet
  620. net_id = (self.provider.networking.subnets
  621. .get(subnet_id).network_id
  622. if subnet_id else None)
  623. zone_id = zone.id if isinstance(zone, PlacementZone) else zone
  624. key_pair_name = key_pair.name if \
  625. isinstance(key_pair, KeyPair) else key_pair
  626. bdm = None
  627. if launch_config:
  628. bdm = self._to_block_device_mapping(launch_config)
  629. # Security groups must be passed in as a list of IDs and attached to a
  630. # port if a port is being created. Otherwise, the security groups must
  631. # be passed in as a list of names to the servers.create() call.
  632. # OpenStack will respect the port's security groups first and then
  633. # fall-back to the named security groups.
  634. sg_name_list = []
  635. nics = None
  636. if subnet_id:
  637. log.debug("Creating network port for %s in subnet: %s",
  638. label, subnet_id)
  639. sg_list = []
  640. if vm_firewalls:
  641. if isinstance(vm_firewalls, list) and \
  642. isinstance(vm_firewalls[0], VMFirewall):
  643. sg_list = vm_firewalls
  644. else:
  645. sg_list = (self.provider.security.vm_firewalls
  646. .find(label=sg) for sg in vm_firewalls)
  647. sg_list = (sg[0] for sg in sg_list if sg)
  648. sg_id_list = [sg.id for sg in sg_list]
  649. port_def = {
  650. "port": {
  651. "admin_state_up": True,
  652. "name": OpenStackInstance._generate_name_from_label(
  653. label, 'cb-port'),
  654. "network_id": net_id,
  655. "fixed_ips": [{"subnet_id": subnet_id}],
  656. "security_groups": sg_id_list
  657. }
  658. }
  659. port_id = self.provider.neutron.create_port(port_def)['port']['id']
  660. nics = [{'net-id': net_id, 'port-id': port_id}]
  661. else:
  662. if vm_firewalls:
  663. if isinstance(vm_firewalls, list) and \
  664. isinstance(vm_firewalls[0], VMFirewall):
  665. sg_name_list = [sg.name for sg in vm_firewalls]
  666. else:
  667. sg_list = (self.provider.security.vm_firewalls.get(sg)
  668. for sg in vm_firewalls)
  669. sg_name_list = (sg[0].name for sg in sg_list if sg)
  670. log.debug("Launching in subnet %s", subnet_id)
  671. os_instance = self.provider.nova.servers.create(
  672. label,
  673. None if self._has_root_device(launch_config) else image_id,
  674. vm_size,
  675. min_count=1,
  676. max_count=1,
  677. availability_zone=zone_id,
  678. key_name=key_pair_name,
  679. security_groups=sg_name_list,
  680. userdata=str(user_data) or None,
  681. block_device_mapping_v2=bdm,
  682. nics=nics)
  683. return OpenStackInstance(self.provider, os_instance)
  684. @dispatch(event="provider.compute.instances.find",
  685. priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
  686. def find(self, **kwargs):
  687. label = kwargs.pop('label', None)
  688. # All kwargs should have been popped at this time.
  689. if len(kwargs) > 0:
  690. raise InvalidParamException(
  691. "Unrecognised parameters for search: %s. Supported "
  692. "attributes: %s" % (kwargs, 'label'))
  693. search_opts = {'name': label}
  694. cb_insts = [
  695. OpenStackInstance(self.provider, inst)
  696. for inst in self.provider.nova.servers.list(
  697. search_opts=search_opts,
  698. limit=oshelpers.os_result_limit(self.provider),
  699. marker=None)]
  700. return oshelpers.to_server_paged_list(self.provider, cb_insts)
  701. @dispatch(event="provider.compute.instances.list",
  702. priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
  703. def list(self, limit=None, marker=None):
  704. """
  705. List all instances.
  706. """
  707. cb_insts = [
  708. OpenStackInstance(self.provider, inst)
  709. for inst in self.provider.nova.servers.list(
  710. limit=oshelpers.os_result_limit(self.provider, limit),
  711. marker=marker)]
  712. return oshelpers.to_server_paged_list(self.provider, cb_insts, limit)
  713. @dispatch(event="provider.compute.instances.get",
  714. priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
  715. def get(self, instance_id):
  716. """
  717. Returns an instance given its id.
  718. """
  719. try:
  720. os_instance = self.provider.nova.servers.get(instance_id)
  721. return OpenStackInstance(self.provider, os_instance)
  722. except NovaNotFound:
  723. log.debug("Instance %s was not found.", instance_id)
  724. return None
  725. @dispatch(event="provider.compute.instances.delete",
  726. priority=BaseInstanceService.STANDARD_EVENT_PRIORITY)
  727. def delete(self, inst):
  728. ins = inst if isinstance(inst, OpenStackInstance) else self.get(inst)
  729. if ins:
  730. # pylint:disable=protected-access
  731. os_instance = ins._os_instance
  732. # delete the port we created when launching
  733. # Assumption: it's the first interface in the list
  734. iface_list = os_instance.interface_list()
  735. if iface_list:
  736. self.provider.neutron.delete_port(iface_list[0].port_id)
  737. os_instance.delete()
  738. class OpenStackVMTypeService(BaseVMTypeService):
  739. def __init__(self, provider):
  740. super(OpenStackVMTypeService, self).__init__(provider)
  741. @dispatch(event="provider.compute.vm_types.list",
  742. priority=BaseVMTypeService.STANDARD_EVENT_PRIORITY)
  743. def list(self, limit=None, marker=None):
  744. cb_itypes = [
  745. OpenStackVMType(self.provider, obj)
  746. for obj in self.provider.nova.flavors.list(
  747. limit=oshelpers.os_result_limit(self.provider, limit),
  748. marker=marker)]
  749. return oshelpers.to_server_paged_list(self.provider, cb_itypes, limit)
  750. class OpenStackRegionService(BaseRegionService):
  751. def __init__(self, provider):
  752. super(OpenStackRegionService, self).__init__(provider)
  753. @dispatch(event="provider.compute.regions.get",
  754. priority=BaseRegionService.STANDARD_EVENT_PRIORITY)
  755. def get(self, region_id):
  756. log.debug("Getting OpenStack Region with the id: %s", region_id)
  757. region = (r for r in self if r.id == region_id)
  758. return next(region, None)
  759. @dispatch(event="provider.compute.regions.list",
  760. priority=BaseRegionService.STANDARD_EVENT_PRIORITY)
  761. def list(self, limit=None, marker=None):
  762. # pylint:disable=protected-access
  763. if self.provider._keystone_version == 3:
  764. os_regions = [OpenStackRegion(self.provider, region)
  765. for region in self.provider.keystone.regions.list()]
  766. return ClientPagedResultList(self.provider, os_regions,
  767. limit=limit, marker=marker)
  768. else:
  769. # Keystone v3 onwards supports directly listing regions
  770. # but for v2, this convoluted method is necessary.
  771. regions = (
  772. endpoint.get('region') or endpoint.get('region_id')
  773. for svc in self.provider.keystone.service_catalog.get_data()
  774. for endpoint in svc.get('endpoints', [])
  775. )
  776. regions = set(region for region in regions if region)
  777. os_regions = [OpenStackRegion(self.provider, region)
  778. for region in regions]
  779. return ClientPagedResultList(self.provider, os_regions,
  780. limit=limit, marker=marker)
  781. @property
  782. def current(self):
  783. nova_region = self.provider.nova.client.region_name
  784. return self.get(nova_region) if nova_region else None
  785. class OpenStackNetworkingService(BaseNetworkingService):
  786. def __init__(self, provider):
  787. super(OpenStackNetworkingService, self).__init__(provider)
  788. self._network_service = OpenStackNetworkService(self.provider)
  789. self._subnet_service = OpenStackSubnetService(self.provider)
  790. self._router_service = OpenStackRouterService(self.provider)
  791. self._gateway_service = OpenStackGatewayService(self.provider)
  792. self._floating_ip_service = OpenStackFloatingIPService(self.provider)
  793. class OpenStackNetworkService(BaseNetworkService):
  794. def __init__(self, provider):
  795. super(OpenStackNetworkService, self).__init__(provider)
  796. @dispatch(event="provider.networking.networks.get",
  797. priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
  798. def get(self, network_id):
  799. network = (n for n in self if n.id == network_id)
  800. return next(network, None)
  801. @dispatch(event="provider.networking.networks.list",
  802. priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
  803. def list(self, limit=None, marker=None):
  804. networks = [OpenStackNetwork(self.provider, network)
  805. for network in self.provider.neutron.list_networks()
  806. .get('networks') if network]
  807. return ClientPagedResultList(self.provider, networks,
  808. limit=limit, marker=marker)
  809. @dispatch(event="provider.networking.networks.find",
  810. priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
  811. def find(self, **kwargs):
  812. label = kwargs.pop('label', None)
  813. # All kwargs should have been popped at this time.
  814. if len(kwargs) > 0:
  815. raise InvalidParamException(
  816. "Unrecognised parameters for search: %s. Supported "
  817. "attributes: %s" % (kwargs, 'label'))
  818. log.debug("Searching for OpenStack Network with label: %s", label)
  819. networks = [OpenStackNetwork(self.provider, network)
  820. for network in self.provider.neutron.list_networks(
  821. name=label)
  822. .get('networks') if network]
  823. return ClientPagedResultList(self.provider, networks)
  824. @dispatch(event="provider.networking.networks.create",
  825. priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
  826. def create(self, label, cidr_block):
  827. OpenStackNetwork.assert_valid_resource_label(label)
  828. net_info = {'name': label or ""}
  829. network = self.provider.neutron.create_network({'network': net_info})
  830. cb_net = OpenStackNetwork(self.provider, network.get('network'))
  831. if label:
  832. cb_net.label = label
  833. return cb_net
  834. @dispatch(event="provider.networking.networks.delete",
  835. priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
  836. def delete(self, net):
  837. network = net if isinstance(net, OpenStackNetwork) else self.get(net)
  838. if not network:
  839. return
  840. if not network.external and network.id in str(
  841. self.provider.neutron.list_networks()):
  842. # If there are ports associated with the network, it won't delete
  843. ports = self.provider.neutron.list_ports(
  844. network_id=network.id).get('ports', [])
  845. for port in ports:
  846. try:
  847. self.provider.neutron.delete_port(port.get('id'))
  848. except PortNotFoundClient:
  849. # Ports could have already been deleted if instances
  850. # are terminated etc. so exceptions can be safely ignored
  851. pass
  852. self.provider.neutron.delete_network(network.id)
  853. class OpenStackSubnetService(BaseSubnetService):
  854. def __init__(self, provider):
  855. super(OpenStackSubnetService, self).__init__(provider)
  856. @dispatch(event="provider.networking.subnets.get",
  857. priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
  858. def get(self, subnet_id):
  859. subnet = (s for s in self if s.id == subnet_id)
  860. return next(subnet, None)
  861. @dispatch(event="provider.networking.subnets.list",
  862. priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
  863. def list(self, network=None, limit=None, marker=None):
  864. if network:
  865. network_id = (network.id if isinstance(network, OpenStackNetwork)
  866. else network)
  867. subnets = [subnet for subnet in self if network_id ==
  868. subnet.network_id]
  869. else:
  870. subnets = [OpenStackSubnet(self.provider, subnet) for subnet in
  871. self.provider.neutron.list_subnets().get('subnets', [])]
  872. return ClientPagedResultList(self.provider, subnets,
  873. limit=limit, marker=marker)
  874. @dispatch(event="provider.networking.subnets.create",
  875. priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
  876. def create(self, label, network, cidr_block, zone):
  877. """zone param is ignored."""
  878. OpenStackSubnet.assert_valid_resource_label(label)
  879. network_id = (network.id if isinstance(network, OpenStackNetwork)
  880. else network)
  881. subnet_info = {'name': label, 'network_id': network_id,
  882. 'cidr': cidr_block, 'ip_version': 4}
  883. subnet = (self.provider.neutron.create_subnet({'subnet': subnet_info})
  884. .get('subnet'))
  885. cb_subnet = OpenStackSubnet(self.provider, subnet)
  886. return cb_subnet
  887. @dispatch(event="provider.networking.subnets.delete",
  888. priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
  889. def delete(self, subnet):
  890. sn_id = subnet.id if isinstance(subnet, OpenStackSubnet) else subnet
  891. self.provider.neutron.delete_subnet(sn_id)
  892. def get_or_create_default(self, zone):
  893. """
  894. Subnet zone is not supported by OpenStack and is thus ignored.
  895. """
  896. try:
  897. sn = self.find(label=OpenStackSubnet.CB_DEFAULT_SUBNET_LABEL)
  898. if sn:
  899. return sn[0]
  900. # No default subnet look for default network, then create subnet
  901. net = self.provider.networking.networks.get_or_create_default()
  902. sn = self.provider.networking.subnets.create(
  903. label=OpenStackSubnet.CB_DEFAULT_SUBNET_LABEL,
  904. cidr_block=OpenStackSubnet.CB_DEFAULT_SUBNET_IPV4RANGE,
  905. network=net, zone=zone)
  906. router = self.provider.networking.routers.get_or_create_default(
  907. net)
  908. router.attach_subnet(sn)
  909. gateway = net.gateways.get_or_create_inet_gateway()
  910. router.attach_gateway(gateway)
  911. return sn
  912. except NeutronClientException:
  913. return None
  914. class OpenStackRouterService(BaseRouterService):
  915. def __init__(self, provider):
  916. super(OpenStackRouterService, self).__init__(provider)
  917. @dispatch(event="provider.networking.routers.get",
  918. priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
  919. def get(self, router_id):
  920. log.debug("Getting OpenStack Router with the id: %s", router_id)
  921. router = self.provider.os_conn.get_router(router_id)
  922. return OpenStackRouter(self.provider, router) if router else None
  923. @dispatch(event="provider.networking.routers.list",
  924. priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
  925. def list(self, limit=None, marker=None):
  926. routers = self.provider.os_conn.list_routers()
  927. os_routers = [OpenStackRouter(self.provider, r) for r in routers]
  928. return ClientPagedResultList(self.provider, os_routers, limit=limit,
  929. marker=marker)
  930. @dispatch(event="provider.networking.routers.find",
  931. priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
  932. def find(self, **kwargs):
  933. obj_list = self
  934. filters = ['label']
  935. matches = cb_helpers.generic_find(filters, kwargs, obj_list)
  936. return ClientPagedResultList(self._provider, list(matches))
  937. @dispatch(event="provider.networking.routers.create",
  938. priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
  939. def create(self, label, network):
  940. """Parameter ``network`` is not used by OpenStack."""
  941. router = self.provider.os_conn.create_router(name=label)
  942. return OpenStackRouter(self.provider, router)
  943. @dispatch(event="provider.networking.routers.delete",
  944. priority=BaseRouterService.STANDARD_EVENT_PRIORITY)
  945. def delete(self, router):
  946. r_id = router.id if isinstance(router, OpenStackRouter) else router
  947. self.provider.os_conn.delete_router(r_id)
  948. class OpenStackGatewayService(BaseGatewayService):
  949. """For OpenStack, an internet gateway is a just an 'external' network."""
  950. def __init__(self, provider):
  951. super(OpenStackGatewayService, self).__init__(provider)
  952. def _check_fip_connectivity(self, network, external_net):
  953. # Due to current limitations in OpenStack:
  954. # https://bugs.launchpad.net/neutron/+bug/1743480, it's not
  955. # possible to differentiate between floating ip networks and provider
  956. # external networks. Therefore, we systematically step through
  957. # all available networks and perform an assignment test to infer valid
  958. # floating ip nets.
  959. dummy_router = self._provider.networking.routers.create(
  960. label='cb-conn-test-router', network=network)
  961. with cb_helpers.cleanup_action(lambda: dummy_router.delete()):
  962. try:
  963. dummy_router.attach_gateway(external_net)
  964. return True
  965. except Exception:
  966. return False
  967. def get_or_create_inet_gateway(self, network):
  968. """For OS, inet gtw is any net that has `external` property set."""
  969. external_nets = (n for n in self._provider.networking.networks
  970. if n.external)
  971. for net in external_nets:
  972. if self._check_fip_connectivity(net):
  973. return OpenStackInternetGateway(self._provider, net)
  974. return None
  975. def delete(self, network, gateway):
  976. log.debug("Deleting OpenStack Gateway: %s", gateway)
  977. gateway.delete()
  978. def list(self, network, limit=None, marker=None):
  979. log.debug("OpenStack listing of all current internet gateways")
  980. igl = [OpenStackInternetGateway(self._provider, n)
  981. for n in self._provider.networking.networks
  982. if n.external and self._check_fip_connectivity(n)]
  983. return ClientPagedResultList(self._provider, igl, limit=limit,
  984. marker=marker)
  985. class OpenStackFloatingIPService(BaseFloatingIPService):
  986. def __init__(self, provider, gateway):
  987. super(OpenStackFloatingIPService, self).__init__(provider, gateway)
  988. def get(self, gateway, fip_id):
  989. try:
  990. return OpenStackFloatingIP(
  991. self.provider, self.provider.os_conn.network.get_ip(fip_id))
  992. except (ResourceNotFound, NotFoundException):
  993. log.debug("Floating IP %s not found.", fip_id)
  994. return None
  995. def list(self, gateway, limit=None, marker=None):
  996. fips = [OpenStackFloatingIP(self.provider, fip)
  997. for fip in self.provider.os_conn.network.ips(
  998. floating_network_id=gateway.id
  999. )]
  1000. return ClientPagedResultList(self.provider, fips,
  1001. limit=limit, marker=marker)
  1002. def create(self, gateway):
  1003. return OpenStackFloatingIP(
  1004. self.provider, self.provider.os_conn.network.create_ip(
  1005. floating_network_id=gateway.id))
  1006. def delete(self, gateway, fip):
  1007. if isinstance(fip, OpenStackFloatingIP):
  1008. os_ip = fip._ip
  1009. else:
  1010. try:
  1011. os_ip = self.provider.os_conn.network.get_ip(fip)
  1012. except (ResourceNotFound, NotFoundException):
  1013. log.debug("Floating IP %s not found.", fip)
  1014. return True
  1015. os_ip.delete(self._provider.os_conn.session)