|
|
@@ -6,10 +6,11 @@ from azure.common import AzureException
|
|
|
|
|
|
from cloudbridge.cloud.base.resources import ClientPagedResultList
|
|
|
from cloudbridge.cloud.base.services import BaseBlockStoreService, \
|
|
|
- BaseComputeService, BaseImageService, BaseInstanceService, \
|
|
|
- BaseInstanceTypesService, BaseKeyPairService, \
|
|
|
- BaseNetworkService, BaseObjectStoreService, \
|
|
|
- BaseRegionService, BaseSecurityGroupService, BaseSecurityService, \
|
|
|
+ BaseComputeService, BaseGatewayService, BaseImageService, \
|
|
|
+ BaseInstanceService, BaseInstanceTypesService, \
|
|
|
+ BaseKeyPairService, BaseNetworkService, BaseNetworkingService, \
|
|
|
+ BaseObjectStoreService, BaseRegionService, BaseRouterService, \
|
|
|
+ BaseSecurityGroupService, BaseSecurityService, \
|
|
|
BaseSnapshotService, BaseSubnetService, BaseVolumeService
|
|
|
from cloudbridge.cloud.interfaces import InvalidConfigurationException
|
|
|
|
|
|
@@ -22,7 +23,8 @@ from cloudbridge.cloud.providers.azure import helpers as azure_helpers
|
|
|
from msrestazure.azure_exceptions import CloudError
|
|
|
|
|
|
from .resources import AzureBucket, AzureFloatingIP, \
|
|
|
- AzureInstance, AzureInstanceType, AzureKeyPair, \
|
|
|
+ AzureInstance, AzureInstanceType, \
|
|
|
+ AzureInternetGateway, AzureKeyPair, \
|
|
|
AzureLaunchConfig, AzureMachineImage, \
|
|
|
AzureNetwork, AzureRegion, AzureRouter, AzureSecurityGroup, \
|
|
|
AzureSnapshot, AzureSubnet, AzureVolume
|
|
|
@@ -106,6 +108,7 @@ class AzureSecurityGroupService(BaseSecurityGroupService):
|
|
|
:rtype: ``object`` of :class:`.SecurityGroup`
|
|
|
:return: A SecurityGroup instance or ``None`` if one was not created.
|
|
|
"""
|
|
|
+ AzureSecurityGroup.assert_valid_resource_name(name)
|
|
|
parameters = {"location": self.provider.region_name,
|
|
|
'tags': {'Name': name}}
|
|
|
|
|
|
@@ -159,7 +162,7 @@ class AzureKeyPairService(BaseKeyPairService):
|
|
|
|
|
|
def get(self, key_pair_id):
|
|
|
try:
|
|
|
- key_pair = self.provider.azure_client. \
|
|
|
+ key_pair = self.provider.azure_client.\
|
|
|
get_public_key(key_pair_id)
|
|
|
|
|
|
if key_pair:
|
|
|
@@ -172,7 +175,7 @@ class AzureKeyPairService(BaseKeyPairService):
|
|
|
def list(self, limit=None, marker=None):
|
|
|
key_pairs = [AzureKeyPair(self.provider, key_pair) for key_pair in
|
|
|
self.provider.azure_client.
|
|
|
- list_public_keys(AzureKeyPairService.PARTITION_KEY)]
|
|
|
+ list_public_keys(AzureKeyPairService.PARTITION_KEY)]
|
|
|
return ClientPagedResultList(self.provider, key_pairs, limit, marker)
|
|
|
|
|
|
def find(self, name, limit=None, marker=None):
|
|
|
@@ -182,6 +185,7 @@ class AzureKeyPairService(BaseKeyPairService):
|
|
|
limit, marker)
|
|
|
|
|
|
def create(self, name):
|
|
|
+ AzureKeyPair.assert_valid_resource_name(name)
|
|
|
|
|
|
key_pair = self.get(name)
|
|
|
|
|
|
@@ -192,11 +196,11 @@ class AzureKeyPairService(BaseKeyPairService):
|
|
|
private_key_str, public_key_str = azure_helpers.gen_key_pair()
|
|
|
|
|
|
entity = {
|
|
|
- 'PartitionKey': AzureKeyPairService.PARTITION_KEY,
|
|
|
- 'RowKey': str(uuid.uuid4()),
|
|
|
- 'Name': name,
|
|
|
- 'Key': public_key_str
|
|
|
- }
|
|
|
+ 'PartitionKey': AzureKeyPairService.PARTITION_KEY,
|
|
|
+ 'RowKey': str(uuid.uuid4()),
|
|
|
+ 'Name': name,
|
|
|
+ 'Key': public_key_str
|
|
|
+ }
|
|
|
|
|
|
self.provider.azure_client.create_public_key(entity)
|
|
|
|
|
|
@@ -247,6 +251,7 @@ class AzureObjectStoreService(BaseObjectStoreService):
|
|
|
"""
|
|
|
Create a new bucket.
|
|
|
"""
|
|
|
+ AzureBucket.assert_valid_resource_name(name)
|
|
|
bucket = self.provider.azure_client.create_container(name.lower())
|
|
|
return AzureBucket(self.provider, bucket)
|
|
|
|
|
|
@@ -308,6 +313,7 @@ class AzureVolumeService(BaseVolumeService):
|
|
|
"""
|
|
|
Creates a new volume.
|
|
|
"""
|
|
|
+ AzureVolume.assert_valid_resource_name(name)
|
|
|
zone_id = zone.id if isinstance(zone, PlacementZone) else zone
|
|
|
snapshot = (self.provider.block_store.snapshots.get(snapshot)
|
|
|
if snapshot and isinstance(snapshot, str) else snapshot)
|
|
|
@@ -386,6 +392,7 @@ class AzureSnapshotService(BaseSnapshotService):
|
|
|
"""
|
|
|
Creates a new snapshot of a given volume.
|
|
|
"""
|
|
|
+ AzureSnapshot.assert_valid_resource_name(name)
|
|
|
volume = (self.provider.block_store.volumes.get(volume)
|
|
|
if isinstance(volume, str) else volume)
|
|
|
|
|
|
@@ -446,7 +453,10 @@ class AzureInstanceService(BaseInstanceService):
|
|
|
key_pair=None, security_groups=None, user_data=None,
|
|
|
launch_config=None, **kwargs):
|
|
|
|
|
|
- instance_name = "{0}-{1}".format(name, uuid.uuid4().hex[:6])
|
|
|
+ instance_name = name.replace("_", "-") if name \
|
|
|
+ else "{0} - {1}".format("cb", uuid.uuid4())
|
|
|
+
|
|
|
+ AzureInstance.assert_valid_resource_name(instance_name)
|
|
|
|
|
|
# Key_pair is mandatory in azure and it should not be None.
|
|
|
if key_pair:
|
|
|
@@ -463,9 +473,9 @@ class AzureInstanceService(BaseInstanceService):
|
|
|
isinstance(instance_type, InstanceType) else instance_type
|
|
|
|
|
|
if not subnet:
|
|
|
- subnet = self.provider.network.subnets.get_or_create_default()
|
|
|
+ subnet = self.provider.networking.subnets.get_or_create_default()
|
|
|
else:
|
|
|
- subnet = (self.provider.network.subnets.get(subnet)
|
|
|
+ subnet = (self.provider.networking.subnets.get(subnet)
|
|
|
if isinstance(subnet, str) else subnet)
|
|
|
|
|
|
zone_id = zone.id if isinstance(zone, PlacementZone) else zone
|
|
|
@@ -483,15 +493,15 @@ class AzureInstanceService(BaseInstanceService):
|
|
|
root_disk_size = None
|
|
|
|
|
|
nic_params = {
|
|
|
- 'location': self._provider.region_name,
|
|
|
- 'ip_configurations': [{
|
|
|
- 'name': instance_name + '_ip_config',
|
|
|
- 'private_ip_allocation_method': 'Dynamic',
|
|
|
- 'subnet': {
|
|
|
- 'id': subnet_id
|
|
|
- }
|
|
|
- }]
|
|
|
- }
|
|
|
+ 'location': self._provider.region_name,
|
|
|
+ 'ip_configurations': [{
|
|
|
+ 'name': instance_name + '_ip_config',
|
|
|
+ 'private_ip_allocation_method': 'Dynamic',
|
|
|
+ 'subnet': {
|
|
|
+ 'id': subnet_id
|
|
|
+ }
|
|
|
+ }]
|
|
|
+ }
|
|
|
|
|
|
if security_group_id:
|
|
|
nic_params['network_security_group'] = {
|
|
|
@@ -503,8 +513,8 @@ class AzureInstanceService(BaseInstanceService):
|
|
|
)
|
|
|
# #! indicates shell script
|
|
|
ud = '#cloud-config\n' + user_data \
|
|
|
- if user_data and not user_data.startswith('#!') \
|
|
|
- and not user_data.startswith('#cloud-config') else user_data
|
|
|
+ if user_data and not user_data.startswith('#!')\
|
|
|
+ and not user_data.startswith('#cloud-config') else user_data
|
|
|
|
|
|
params = {
|
|
|
'location': zone_id or self._provider.region_name,
|
|
|
@@ -512,16 +522,16 @@ class AzureInstanceService(BaseInstanceService):
|
|
|
'admin_username': self.provider.vm_default_user_name,
|
|
|
'computer_name': instance_name,
|
|
|
'linux_configuration': {
|
|
|
- "disable_password_authentication": True,
|
|
|
- "ssh": {
|
|
|
- "public_keys": [{
|
|
|
- "path":
|
|
|
- "/home/{}/.ssh/authorized_keys".format(
|
|
|
- self.provider.vm_default_user_name),
|
|
|
- "key_data": key_pair._key_pair.Key
|
|
|
- }]
|
|
|
- }
|
|
|
- }
|
|
|
+ "disable_password_authentication": True,
|
|
|
+ "ssh": {
|
|
|
+ "public_keys": [{
|
|
|
+ "path":
|
|
|
+ "/home/{}/.ssh/authorized_keys".format(
|
|
|
+ self.provider.vm_default_user_name),
|
|
|
+ "key_data": key_pair._key_pair.Key
|
|
|
+ }]
|
|
|
+ }
|
|
|
+ }
|
|
|
},
|
|
|
'hardware_profile': {
|
|
|
'vm_size': instance_size
|
|
|
@@ -593,12 +603,12 @@ class AzureInstanceService(BaseInstanceService):
|
|
|
security_group_id = security_groups[0].resource_id
|
|
|
else:
|
|
|
security_groups_ids = security_groups
|
|
|
- seuciry_group = self.provider.security. \
|
|
|
+ seuciry_group = self.provider.security.\
|
|
|
security_groups.get(security_groups[0])
|
|
|
security_group_id = seuciry_group.resource_id
|
|
|
|
|
|
if len(security_groups) > 1:
|
|
|
- new_sg = self.provider.security.security_groups. \
|
|
|
+ new_sg = self.provider.security.security_groups.\
|
|
|
create('{0}-sg'.format(name), 'Merge security groups {0}'.
|
|
|
format(','.join(security_groups_ids)))
|
|
|
|
|
|
@@ -637,7 +647,7 @@ class AzureInstanceService(BaseInstanceService):
|
|
|
# This method uses the azure tags functionality to store
|
|
|
# the delete_on_terminate option when the virtual machine
|
|
|
# is deleted, we parse the tags and delete accordingly
|
|
|
- self.provider.azure_client. \
|
|
|
+ self.provider.azure_client.\
|
|
|
update_disk_tags(volume.id, volume.tags)
|
|
|
|
|
|
for device in launch_config.block_devices:
|
|
|
@@ -763,6 +773,7 @@ class AzureImageService(BaseImageService):
|
|
|
|
|
|
|
|
|
class AzureInstanceTypesService(BaseInstanceTypesService):
|
|
|
+
|
|
|
def __init__(self, provider):
|
|
|
super(AzureInstanceTypesService, self).__init__(provider)
|
|
|
|
|
|
@@ -781,10 +792,34 @@ class AzureInstanceTypesService(BaseInstanceTypesService):
|
|
|
limit=limit, marker=marker)
|
|
|
|
|
|
|
|
|
+class AzureNetworkingService(BaseNetworkingService):
|
|
|
+ def __init__(self, provider):
|
|
|
+ super(AzureNetworkingService, self).__init__(provider)
|
|
|
+ self._network_service = AzureNetworkService(self.provider)
|
|
|
+ self._subnet_service = AzureSubnetService(self.provider)
|
|
|
+ self._router_service = AzureRouterService(self.provider)
|
|
|
+ self._gateway_service = AzureGatewayService(self.provider)
|
|
|
+
|
|
|
+ @property
|
|
|
+ def networks(self):
|
|
|
+ return self._network_service
|
|
|
+
|
|
|
+ @property
|
|
|
+ def subnets(self):
|
|
|
+ return self._subnet_service
|
|
|
+
|
|
|
+ @property
|
|
|
+ def routers(self):
|
|
|
+ return self._router_service
|
|
|
+
|
|
|
+ @property
|
|
|
+ def gateways(self):
|
|
|
+ return self._gateway_service
|
|
|
+
|
|
|
+
|
|
|
class AzureNetworkService(BaseNetworkService):
|
|
|
def __init__(self, provider):
|
|
|
super(AzureNetworkService, self).__init__(provider)
|
|
|
- self._subnet_svc = AzureSubnetService(self.provider)
|
|
|
|
|
|
def get(self, network_id):
|
|
|
try:
|
|
|
@@ -805,25 +840,33 @@ class AzureNetworkService(BaseNetworkService):
|
|
|
return ClientPagedResultList(self.provider, networks,
|
|
|
limit=limit, marker=marker)
|
|
|
|
|
|
- def create(self, name=None):
|
|
|
+ def find(self, name, limit=None, marker=None):
|
|
|
+ filters = {'Name': name}
|
|
|
+ networks = [AzureNetwork(self.provider, network)
|
|
|
+ for network in azure_helpers.filter(
|
|
|
+ self.provider.azure_client.list_networks(), filters)]
|
|
|
+ return ClientPagedResultList(self.provider, networks,
|
|
|
+ limit=limit, marker=marker)
|
|
|
+
|
|
|
+ def create(self, name, cidr_block):
|
|
|
# Azure requires CIDR block to be specified when creating a network
|
|
|
# so set a default one and use the largest allowed netmask.
|
|
|
network_name = AzureNetwork.CB_DEFAULT_NETWORK_NAME
|
|
|
if name:
|
|
|
network_name = "{0}-{1}".format(name, uuid.uuid4().hex[:6])
|
|
|
|
|
|
+ AzureNetwork.assert_valid_resource_name(network_name)
|
|
|
+
|
|
|
params = {
|
|
|
'location': self.provider.azure_client.region_name,
|
|
|
'address_space': {
|
|
|
- 'address_prefixes': ['10.0.0.0/16']
|
|
|
+ 'address_prefixes': [cidr_block]
|
|
|
},
|
|
|
'tags': {'Name': name or AzureNetwork.CB_DEFAULT_NETWORK_NAME}
|
|
|
}
|
|
|
-
|
|
|
self.provider.azure_client.create_network(network_name, params)
|
|
|
network = self.provider.azure_client.get_network(network_name)
|
|
|
cb_network = AzureNetwork(self.provider, network)
|
|
|
-
|
|
|
return cb_network
|
|
|
|
|
|
def create_floating_ip(self):
|
|
|
@@ -834,32 +877,20 @@ class AzureNetworkService(BaseNetworkService):
|
|
|
'public_ip_allocation_method': 'Static'
|
|
|
}
|
|
|
|
|
|
- floating_ip = self.provider.azure_client. \
|
|
|
+ floating_ip = self.provider.azure_client.\
|
|
|
create_floating_ip(public_ip_address_name, public_ip_parameters)
|
|
|
return AzureFloatingIP(self.provider, floating_ip)
|
|
|
|
|
|
@property
|
|
|
- def subnets(self):
|
|
|
- return self._subnet_svc
|
|
|
-
|
|
|
- def floating_ips(self, network_id=None):
|
|
|
+ def floating_ips(self):
|
|
|
"""
|
|
|
List all floating ips.
|
|
|
"""
|
|
|
floating_ips = [AzureFloatingIP(self.provider, floating_ip)
|
|
|
for floating_ip in self.provider.azure_client.
|
|
|
- list_floating_ips()]
|
|
|
-
|
|
|
+ list_floating_ips()]
|
|
|
return ClientPagedResultList(self.provider, floating_ips)
|
|
|
|
|
|
- def routers(self):
|
|
|
- return ClientPagedResultList(self.provider, [])
|
|
|
-
|
|
|
- def create_router(self, name=None):
|
|
|
- ar = AzureRouter(self.provider, None)
|
|
|
- ar.name = name
|
|
|
- return ar
|
|
|
-
|
|
|
def delete(self, network_id):
|
|
|
"""
|
|
|
Delete an existing network.
|
|
|
@@ -897,6 +928,7 @@ class AzureRegionService(BaseRegionService):
|
|
|
|
|
|
|
|
|
class AzureSubnetService(BaseSubnetService):
|
|
|
+
|
|
|
def __init__(self, provider):
|
|
|
super(AzureSubnetService, self).__init__(provider)
|
|
|
|
|
|
@@ -912,7 +944,9 @@ class AzureSubnetService(BaseSubnetService):
|
|
|
"""
|
|
|
try:
|
|
|
subnet_id_parts = subnet_id.split('|$|')
|
|
|
- azure_subnet = self.provider.azure_client. \
|
|
|
+ if (len(subnet_id_parts) != 2):
|
|
|
+ return None
|
|
|
+ azure_subnet = self.provider.azure_client.\
|
|
|
get_subnet(subnet_id_parts[0], subnet_id_parts[1])
|
|
|
return AzureSubnet(self.provider,
|
|
|
azure_subnet) if azure_subnet else None
|
|
|
@@ -949,6 +983,7 @@ class AzureSubnetService(BaseSubnetService):
|
|
|
"""
|
|
|
Create subnet
|
|
|
"""
|
|
|
+ AzureSubnet.assert_valid_resource_name(name)
|
|
|
network_id = network.id \
|
|
|
if isinstance(network, Network) else network
|
|
|
|
|
|
@@ -957,14 +992,14 @@ class AzureSubnetService(BaseSubnetService):
|
|
|
else:
|
|
|
subnet_name = name
|
|
|
|
|
|
- subnet_info = self.provider.azure_client \
|
|
|
+ subnet_info = self.provider.azure_client\
|
|
|
.create_subnet(
|
|
|
- network_id,
|
|
|
- subnet_name,
|
|
|
- {
|
|
|
- 'address_prefix': cidr_block
|
|
|
- }
|
|
|
- )
|
|
|
+ network_id,
|
|
|
+ subnet_name,
|
|
|
+ {
|
|
|
+ 'address_prefix': cidr_block
|
|
|
+ }
|
|
|
+ )
|
|
|
|
|
|
return AzureSubnet(self.provider, subnet_info)
|
|
|
|
|
|
@@ -987,18 +1022,20 @@ class AzureSubnetService(BaseSubnetService):
|
|
|
return AzureSubnet(self.provider, subnet)
|
|
|
|
|
|
# No provider-default Subnet exists, try to create it (net + subnets)
|
|
|
+ default_net_name = AzureNetwork.CB_DEFAULT_NETWORK_NAME
|
|
|
try:
|
|
|
network = self.provider.azure_client \
|
|
|
- .get_network(AzureNetwork.CB_DEFAULT_NETWORK_NAME)
|
|
|
+ .get_network(default_net_name)
|
|
|
except CloudError:
|
|
|
# Azure raises the cloud error if the resource not available
|
|
|
pass
|
|
|
|
|
|
if not network:
|
|
|
- self.provider.network.create()
|
|
|
+ network = self.provider.networking.networks.create(
|
|
|
+ name=default_net_name, cidr_block='10.0.0.0/16')
|
|
|
|
|
|
subnet = self.provider.azure_client.create_subnet(
|
|
|
- AzureNetwork.CB_DEFAULT_NETWORK_NAME,
|
|
|
+ network.id,
|
|
|
AzureSubnet.CB_DEFAULT_SUBNET_NAME,
|
|
|
{'address_prefix': default_cdir}
|
|
|
)
|
|
|
@@ -1013,10 +1050,65 @@ class AzureSubnetService(BaseSubnetService):
|
|
|
|
|
|
subnet_id = subnet.id if isinstance(subnet, Subnet) else subnet
|
|
|
subnet_id_parts = subnet_id.split('|$|')
|
|
|
- self.provider.azure_client. \
|
|
|
+ self.provider.azure_client.\
|
|
|
delete_subnet(subnet_id_parts[0], subnet_id_parts[1])
|
|
|
return True
|
|
|
except CloudError as cloudError:
|
|
|
# Azure raises the cloud error if the resource not available
|
|
|
log.exception(cloudError.message)
|
|
|
return False
|
|
|
+
|
|
|
+
|
|
|
+class AzureRouterService(BaseRouterService):
|
|
|
+ def __init__(self, provider):
|
|
|
+ super(AzureRouterService, self).__init__(provider)
|
|
|
+
|
|
|
+ def get(self, router_id):
|
|
|
+ try:
|
|
|
+ route = self.provider.azure_client.get_route_table(router_id)
|
|
|
+ return AzureRouter(self.provider, route)
|
|
|
+
|
|
|
+ except CloudError as cloudError:
|
|
|
+ # Azure raises the cloud error if the resource not available
|
|
|
+ log.exception(cloudError.message)
|
|
|
+ return None
|
|
|
+
|
|
|
+ def find(self, name, limit=None, marker=None):
|
|
|
+ filters = {'Name': name}
|
|
|
+ routes = [AzureRouter(self.provider, route)
|
|
|
+ for route in azure_helpers.filter(
|
|
|
+ self.provider.azure_client.list_route_tables(), filters)]
|
|
|
+
|
|
|
+ return ClientPagedResultList(self.provider, routes,
|
|
|
+ limit=limit, marker=marker)
|
|
|
+
|
|
|
+ def list(self, limit=None, marker=None):
|
|
|
+ routes = [AzureRouter(self.provider, route)
|
|
|
+ for route in
|
|
|
+ self.provider.azure_client.list_route_tables()]
|
|
|
+ return ClientPagedResultList(self.provider,
|
|
|
+ routes,
|
|
|
+ limit=limit, marker=marker)
|
|
|
+
|
|
|
+ def create(self, name, network):
|
|
|
+ AzureRouter.assert_valid_resource_name(name)
|
|
|
+ parameters = {"location": self.provider.region_name,
|
|
|
+ 'tags': {'Name': name}}
|
|
|
+ route = self.provider.azure_client. \
|
|
|
+ create_route_table(name, parameters)
|
|
|
+ return AzureRouter(self.provider, route)
|
|
|
+
|
|
|
+
|
|
|
+class AzureGatewayService(BaseGatewayService):
|
|
|
+ def __init__(self, provider):
|
|
|
+ super(AzureGatewayService, self).__init__(provider)
|
|
|
+
|
|
|
+ def get_or_create_inet_gateway(self, name):
|
|
|
+ AzureInternetGateway.assert_valid_resource_name(name)
|
|
|
+
|
|
|
+ gateway = AzureInternetGateway(self.provider, None)
|
|
|
+ gateway.name = name
|
|
|
+ return gateway
|
|
|
+
|
|
|
+ def delete(self, gateway):
|
|
|
+ pass
|