"""
Driver class for keystoneclient V2 APIs
"""
- def __init__(self, username, password, auth_url,tenant_name, insecure):
+ def __init__(self, username, password, auth_url,tenant_name, insecure, region):
"""
Constructor for KeystoneDriverV3 class
Arguments:
password (string) : Password
auth_url (string) : Authentication URL
tenant_name(string): Tenant Name
-
+ region (string) : Region name
Returns: None
"""
self._username = username
self._auth_url = auth_url
self._tenant_name = tenant_name
self._insecure = insecure
+ self._region = region
super(KeystoneDriverV2, self).__init__(ksclientv2.Client)
def _get_keystone_credentials(self):
creds['auth_url'] = self._auth_url
creds['tenant_name'] = self._tenant_name
creds['insecure'] = self.get_security_mode()
+ creds['region_name'] = self._region
return creds
def get_auth_token(self):
"""
Driver class for keystoneclient V3 APIs
"""
- def __init__(self, username, password, auth_url,tenant_name, insecure, user_domain_name = None, project_domain_name = None):
+ def __init__(self, username,
+ password,
+ auth_url,
+ tenant_name,
+ insecure,
+ user_domain_name = None,
+ project_domain_name = None,
+ region = None):
"""
Constructor for KeystoneDriverV3 class
Arguments:
password (string) : Password
auth_url (string) : Authentication URL
tenant_name(string): Tenant Name
-
+ user_domain_name (string) : User domain name
+ project_domain_name (string): Project domain name
+ region (string) : Region name
Returns: None
"""
self._username = username
self._insecure = insecure
self._user_domain_name = user_domain_name
self._project_domain_name = project_domain_name
+ self._region = region
super(KeystoneDriverV3, self).__init__(ksclientv3.Client)
def _get_keystone_credentials(self):
creds['insecure'] = self._insecure
creds['user_domain_name'] = self._user_domain_name
creds['project_domain_name'] = self._project_domain_name
+ creds['region_name'] = self._region
return creds
def get_user_domain_name(self):
creds['project_id'] = self.ks_drv.get_tenant_name()
creds['auth_token'] = self.ks_drv.get_auth_token()
creds['insecure'] = self.ks_drv.get_security_mode()
- creds['user_domain_name'] = self.ks_drv.get_user_domain_name()
- creds['project_domain_name'] = self.ks_drv.get_project_domain_name()
+ #creds['user_domain_name'] = self.ks_drv.get_user_domain_name()
+ #creds['project_domain_name'] = self.ks_drv.get_project_domain_name()
return creds
"""
Driver for openstack nova, neutron, glance, keystone, swift, cinder services
"""
- def __init__(self, username, password, auth_url, tenant_name, mgmt_network = None, cert_validate = False, user_domain_name = None, project_domain_name = None):
+ def __init__(self, username,
+ password,
+ auth_url,
+ tenant_name,
+ mgmt_network = None,
+ cert_validate = False,
+ user_domain_name = None,
+ project_domain_name = None,
+ region = None):
"""
OpenstackDriver Driver constructor
Arguments:
mgmt_network(string, optional) : Management network name. Each VM created with this cloud-account will
have a default interface into management network.
cert_validate (boolean, optional) : In case of SSL/TLS connection if certificate validation is required or not.
-
+ user_domain_name : Domain name for user
+ project_domain_name : Domain name for project
+ region : Region name
"""
insecure = not cert_validate
if auth_url.find('/v3') != -1:
- self.ks_drv = KeystoneDriverV3(username, password, auth_url, tenant_name, insecure, user_domain_name, project_domain_name)
+ self.ks_drv = KeystoneDriverV3(username,
+ password,
+ auth_url,
+ tenant_name,
+ insecure,
+ user_domain_name,
+ project_domain_name,
+ region)
self.glance_drv = GlanceDriverV2(self.ks_drv)
self.nova_drv = NovaDriverV21(self.ks_drv)
self.neutron_drv = NeutronDriverV2(self.ks_drv)
self.ceilo_drv = CeilometerDriverV2(self.ks_drv)
self.cinder_drv = CinderDriverV2(self.ks_drv)
elif auth_url.find('/v2') != -1:
- self.ks_drv = KeystoneDriverV2(username, password, auth_url, tenant_name, insecure)
+
+ self.ks_drv = KeystoneDriverV2(username,
+ password,
+ auth_url,
+ tenant_name,
+ insecure,
+ region)
self.glance_drv = GlanceDriverV2(self.ks_drv)
self.nova_drv = NovaDriverV2(self.ks_drv)
self.neutron_drv = NeutronDriverV2(self.ks_drv)
import sys, os, time
import rwlogger
import yaml
+import random
+import fcntl
+
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger()
logger.addHandler(rwlog_handler)
#logger.setLevel(logging.DEBUG)
+class FileLock:
+ FILE_LOCK = '/tmp/_openstack_prepare_vm.lock'
+ def __init__(self):
+ # This will create it if it does not exist already
+ self.filename = FileLock.FILE_LOCK
+ self.handle = None
+
+ # Bitwise OR fcntl.LOCK_NB if you need a non-blocking lock
+ def acquire(self):
+ logger.info("<PID: %d> Attempting to acquire log." %os.getpid())
+ self.handle = open(self.filename, 'w')
+ fcntl.flock(self.handle, fcntl.LOCK_EX)
+ logger.info("<PID: %d> Lock successfully acquired." %os.getpid())
+
+ def release(self):
+ fcntl.flock(self.handle, fcntl.LOCK_UN)
+ self.handle.close()
+ logger.info("<PID: %d> Released lock." %os.getpid())
+
+ def __del__(self):
+ if self.handle and self.handle.closed == False:
+ self.handle.close()
+
+
+def allocate_floating_ip(drv, argument):
+ #### Allocate a floating_ip
+ available_ip = [ ip for ip in drv.nova_floating_ip_list() if ip.instance_id == None ]
+
+ if argument.pool_name:
+ ### Filter further based on IP address
+ available_ip = [ ip for ip in available_ip if ip.pool == argument.pool_name ]
+
+ if not available_ip:
+ logger.info("<PID: %d> No free floating_ips available. Allocating fresh from pool: %s" %(os.getpid(), argument.pool_name))
+ pool_name = argument.pool_name if argument.pool_name is not None else None
+ floating_ip = drv.nova_floating_ip_create(pool_name)
+ else:
+ floating_ip = random.choice(available_ip)
+ logger.info("<PID: %d> Selected floating_ip: %s from available free pool" %(os.getpid(), floating_ip))
+
+ return floating_ip
+
+def handle_floating_ip_assignment(drv, server, argument, management_ip):
+ lock = FileLock()
+ ### Try 3 time (<<<magic number>>>)
+ RETRY = 3
+ for attempt in range(RETRY):
+ try:
+ lock.acquire()
+ floating_ip = allocate_floating_ip(drv, argument)
+ logger.info("Assigning the floating_ip: %s to VM: %s" %(floating_ip, server['name']))
+ drv.nova_floating_ip_assign(argument.server_id,
+ floating_ip,
+ management_ip)
+ logger.info("Assigned floating_ip: %s to management_ip: %s" %(floating_ip, management_ip))
+ except Exception as e:
+ logger.error("Could not assign floating_ip: %s to VM: %s. Exception: %s" %(floating_ip, server['name'], str(e)))
+ lock.release()
+ if attempt == (RETRY -1):
+ logger.error("Max attempts %d reached for floating_ip allocation. Giving up" %attempt)
+ raise
+ else:
+ logger.error("Retrying floating ip allocation. Current retry count: %d" %attempt)
+ else:
+ lock.release()
+ return
+
+
def assign_floating_ip_address(drv, argument):
if not argument.floating_ip:
return
server = drv.nova_server_get(argument.server_id)
- logger.info("Assigning the floating_ip: %s to VM: %s" %(argument.floating_ip, server['name']))
-
+
for i in range(120):
server = drv.nova_server_get(argument.server_id)
for network_name,network_info in server['addresses'].items():
- if network_info:
- if network_name == argument.mgmt_network:
- for n_info in network_info:
- if 'OS-EXT-IPS:type' in n_info and n_info['OS-EXT-IPS:type'] == 'fixed':
- management_ip = n_info['addr']
- drv.nova_floating_ip_assign(argument.server_id,
- argument.floating_ip,
- management_ip)
- logger.info("Assigned floating_ip: %s to management_ip: %s" %(argument.floating_ip, management_ip))
+ if network_info and network_name == argument.mgmt_network:
+ for n_info in network_info:
+ if 'OS-EXT-IPS:type' in n_info and n_info['OS-EXT-IPS:type'] == 'fixed':
+ management_ip = n_info['addr']
+ handle_floating_ip_assignment(drv, server, argument, management_ip)
return
- logger.info("Waiting for management_ip to be assigned to server: %s" %(server['name']))
- time.sleep(1)
+ else:
+ logger.info("Waiting for management_ip to be assigned to server: %s" %(server['name']))
+ time.sleep(1)
else:
logger.info("No management_ip IP available to associate floating_ip for server: %s" %(server['name']))
return
type = str,
help = "Tenant name openstack installation")
+ parser.add_argument('--user_domain',
+ action = "store",
+ dest = "user_domain",
+ default = None,
+ type = str,
+ help = "User domain name for openstack installation")
+
+ parser.add_argument('--project_domain',
+ action = "store",
+ dest = "project_domain",
+ default = None,
+ type = str,
+ help = "Project domain name for openstack installation")
+
+ parser.add_argument('--region',
+ action = "store",
+ dest = "region",
+ default = "RegionOne",
+ type = str,
+ help = "Region name for openstack installation")
+
parser.add_argument('--mgmt_network',
action = "store",
dest = "mgmt_network",
help = "Server ID on which boot operations needs to be performed")
parser.add_argument('--floating_ip',
- action = "store",
+ action = "store_true",
dest = "floating_ip",
+ default = False,
+ help = "Floating IP assignment required")
+
+ parser.add_argument('--pool_name',
+ action = "store",
+ dest = "pool_name",
type = str,
- help = "Floating IP to be assigned")
+ help = "Floating IP pool name")
+
parser.add_argument('--port_metadata',
action = "store_true",
else:
logger.info("Using Server ID : %s" %(argument.server_id))
-
try:
pid = os.fork()
if pid > 0:
except OSError as e:
logger.error("fork failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(2)
-
- drv = openstack_drv.OpenstackDriver(username = argument.username,
- password = argument.password,
- auth_url = argument.auth_url,
- tenant_name = argument.tenant_name,
- mgmt_network = argument.mgmt_network)
+
+
+ drv = openstack_drv.OpenstackDriver(username = argument.username,
+ password = argument.password,
+ auth_url = argument.auth_url,
+ tenant_name = argument.tenant_name,
+ mgmt_network = argument.mgmt_network,
+ user_domain_name = argument.user_domain,
+ project_domain_name = argument.project_domain,
+ region = argument.region)
+
prepare_vm_after_boot(drv, argument)
sys.exit(0)
RwTypes,
RwcalYang)
-PREPARE_VM_CMD = "prepare_vm.py --auth_url {auth_url} --username {username} --password {password} --tenant_name {tenant_name} --mgmt_network {mgmt_network} --server_id {server_id} --port_metadata"
+PREPARE_VM_CMD = "prepare_vm.py --auth_url {auth_url} --username {username} --password {password} --tenant_name {tenant_name} --region {region} --user_domain {user_domain} --project_domain {project_domain} --mgmt_network {mgmt_network} --server_id {server_id} --port_metadata "
rwstatus_exception_map = { IndexError: RwTypes.RwStatus.NOTFOUND,
KeyError: RwTypes.RwStatus.NOTFOUND,
mgmt_network = account.openstack.mgmt_network,
cert_validate = account.openstack.cert_validate,
user_domain_name = account.openstack.user_domain,
- project_domain_name = account.openstack.project_domain)
+ project_domain_name = account.openstack.project_domain,
+ region = account.openstack.region)
except (KeystoneExceptions.Unauthorized, KeystoneExceptions.AuthorizationFailure,
NeutronException.NotFound) as e:
raise
with self._use_driver(account) as drv:
### If floating_ip is required and we don't have one, better fail before any further allocation
+ pool_name = None
+ floating_ip = False
if vminfo.has_field('allocate_public_address') and vminfo.allocate_public_address:
if account.openstack.has_field('floating_ip_pool'):
pool_name = account.openstack.floating_ip_pool
- else:
- pool_name = None
- floating_ip = self._allocate_floating_ip(drv, pool_name)
- else:
- floating_ip = None
+ floating_ip = True
if vminfo.has_field('cloud_init') and vminfo.cloud_init.has_field('userdata'):
kwargs['userdata'] = vminfo.cloud_init.userdata
vdu.public_ip = interface['addr']
# Look for any metadata
- for key, value in vm_info['metadata'].items():
- if key == 'node_id':
- vdu.node_id = value
- else:
- custommetadata = vdu.supplemental_boot_data.custom_meta_data.add()
- custommetadata.name = key
- custommetadata.value = str(value)
+# for key, value in vm_info['metadata'].items():
+# if key == 'node_id':
+# vdu.node_id = value
+# else:
+# custommetadata = vdu.supplemental_boot_data.custom_meta_data.add()
+# custommetadata.name = key
+# custommetadata.value = str(value)
# Look for config_drive
if ('config_drive' in vm_info):
with self._use_driver(account) as drv:
### If floating_ip is required and we don't have one, better fail before any further allocation
+ floating_ip = False
+ pool_name = None
if vduinfo.has_field('allocate_public_address') and vduinfo.allocate_public_address:
if account.openstack.has_field('floating_ip_pool'):
pool_name = account.openstack.floating_ip_pool
- else:
- pool_name = None
- floating_ip = self._allocate_floating_ip(drv, pool_name)
- else:
- floating_ip = None
+ floating_ip = True
if vduinfo.has_field('vdu_init') and vduinfo.vdu_init.has_field('userdata'):
kwargs['userdata'] = vduinfo.vdu_init.userdata
with self._use_driver(account) as drv:
vm_id = drv.nova_server_create(**kwargs)
if floating_ip:
- self.prepare_vdu_on_boot(account, vm_id, floating_ip, vduinfo.volumes)
+ self.prepare_vdu_on_boot(account, vm_id, floating_ip, pool_name, vduinfo.volumes)
return vm_id
mgmt_network_id = None
with self._use_driver(account) as drv:
mgmt_network_id = drv._mgmt_network_id
- ### If floating_ip is required and we don't have one, better fail before any further allocation
- if vdu_init.has_field('allocate_public_address') and vdu_init.allocate_public_address:
- if account.openstack.has_field('floating_ip_pool'):
- pool_name = account.openstack.floating_ip_pool
- else:
- pool_name = None
- floating_ip = self._allocate_floating_ip(drv, pool_name)
- else:
- floating_ip = None
port_list = []
network_list = []
- def prepare_vdu_on_boot(self, account, server_id, floating_ip, volumes=None):
- cmd = PREPARE_VM_CMD.format(auth_url = account.openstack.auth_url,
- username = account.openstack.key,
- password = account.openstack.secret,
- tenant_name = account.openstack.tenant,
- mgmt_network = account.openstack.mgmt_network,
- server_id = server_id)
-
- if floating_ip is not None:
- cmd += (" --floating_ip "+ floating_ip.ip)
+ def prepare_vdu_on_boot(self, account, server_id, floating_ip, pool_name, volumes=None):
+ cmd = PREPARE_VM_CMD.format(auth_url = account.openstack.auth_url,
+ username = account.openstack.key,
+ password = account.openstack.secret,
+ tenant_name = account.openstack.tenant,
+ region = account.openstack.region,
+ user_domain = account.openstack.user_domain,
+ project_domain = account.openstack.project_domain,
+ mgmt_network = account.openstack.mgmt_network,
+ server_id = server_id)
+ if floating_ip:
+ cmd += " --floating_ip"
+ if pool_name:
+ cmd += (" --pool_name " + pool_name)
vol_metadata = False
if volumes is not None:
mandatory true;
}
+ leaf region {
+ type string;
+ default "RegionOne";
+ }
+
leaf admin {
type boolean;
default false;