Source code for pebbles.drivers.provisioning.openstack_driver
""" ToDo: document OpenStack driver on user level here.
"""
import json
from pebbles.services.openstack_service import OpenStackService
from pebbles.drivers.provisioning import base_driver
from pebbles.client import PBClient
from pebbles.models import Instance
from pebbles.utils import parse_ports_string
SLEEP_BETWEEN_POLLS = 3
POLL_MAX_WAIT = 180
[docs]class OpenStackDriver(base_driver.ProvisioningDriverBase):
""" ToDo: document Openstack driver on developer/sysadmin level here.
"""
def get_oss(self):
return OpenStackService({'M2M_CREDENTIAL_STORE': self.config['M2M_CREDENTIAL_STORE']})
def get_configuration(self):
from pebbles.drivers.provisioning.openstack_driver_config import CONFIG
oss = self.get_oss()
images = [x.name for x in oss.list_images()]
flavors = [x.name for x in oss.list_flavors()]
config = CONFIG.copy()
config['schema']['properties']['image']['enum'] = images
config['schema']['properties']['flavor']['enum'] = flavors
return config
def get_running_instance_logs(self, token, instance_id):
running_log_uploader = self.create_prov_log_uploader(token, instance_id, log_type='running')
running_log_uploader.info('Cannot get running logs. This feature has not been implemented for the OpenStackDriver yet')
def do_update_connectivity(self, token, instance_id):
oss = self.get_oss()
pbclient = PBClient(token, self.config['INTERNAL_API_BASE_URL'], ssl_verify=False)
instance = pbclient.get_instance_description(instance_id)
instance_data = instance['instance_data']
security_group_id = instance_data['security_group_id']
blueprint_config = pbclient.get_blueprint_description(instance['blueprint_id'])
config = blueprint_config['full_config']
# Delete all existing rules and add the rules using the input port string
oss.clear_security_group_rules(security_group_id)
ports_str = config['exposed_ports']
if not ports_str:
ports_str = '22' # If the input port string is empty then use 22 as the default port
ports_list = parse_ports_string(ports_str)
for ports in ports_list:
from_port = ports[0]
to_port = ports[1]
oss.create_security_group_rule(
security_group_id,
from_port=from_port,
to_port=to_port,
cidr="%s/32" % instance['client_ip'],
ip_protocol='tcp',
group_id=None
)
def do_provision(self, token, instance_id):
self.logger.debug("do_provision %s" % instance_id)
pbclient = PBClient(token, self.config['INTERNAL_API_BASE_URL'], ssl_verify=False)
instance = pbclient.get_instance_description(instance_id)
instance_name = instance['name']
instance_user = instance['user_id']
# fetch config
blueprint_config = pbclient.get_blueprint_description(instance['blueprint_id'])
config = blueprint_config['full_config']
log_uploader = self.create_prov_log_uploader(token, instance_id, log_type='provisioning')
log_uploader.info("Provisioning OpenStack instance (%s)\n" % instance_id)
ports_str = config['exposed_ports']
if ports_str:
try:
parse_ports_string(ports_str)
except:
error = 'Incorrect exposed ports definition in blueprint'
error_body = {'state': Instance.STATE_FAILED, 'error_msg': error}
pbclient.do_instance_patch(instance_id, error_body)
self.logger.debug(error)
raise RuntimeError(error)
# fetch user public key
key_data = pbclient.get_user_key_data(instance_user).json()
if not key_data:
error = 'user\'s public key is missing'
error_body = {'state': Instance.STATE_FAILED, 'error_msg': error}
pbclient.do_instance_patch(instance_id, error_body)
self.logger.debug(error)
raise RuntimeError(error)
oss = self.get_oss()
result = oss.provision_instance(
instance_name,
config['image'],
config['flavor'],
nics=config.get('openstack_net_id', 'auto'),
public_key=key_data[0]['public_key'],
userdata=config.get('userdata'))
if 'error' in result:
log_uploader.warn('Provisioning failed %s' % result['error'])
return
ip = result['address_data']['public_ip']
instance_data = {
'server_id': result['server_id'],
'floating_ip': ip,
'allocated_from_pool': result['address_data']['allocated_from_pool'],
'security_group_id': result['security_group'],
'endpoints': [
{'name': 'SSH', 'access': 'ssh cloud-user@%s' % ip},
]
}
log_uploader.info("Publishing server data\n")
pbclient.do_instance_patch(
instance_id,
{'instance_data': json.dumps(instance_data), 'public_ip': ip})
log_uploader.info("Provisioning complete\n")
def do_deprovision(self, token, instance_id):
log_uploader = self.create_prov_log_uploader(token, instance_id, log_type='deprovisioning')
log_uploader.info("Deprovisioning instance %s\n" % instance_id)
pbclient = PBClient(token, self.config['INTERNAL_API_BASE_URL'], ssl_verify=False)
oss = self.get_oss()
instance = pbclient.get_instance_description(instance_id)
instance_data = instance['instance_data']
if 'server_id' not in instance_data:
log_uploader.info("Skipping, no server id in instance data")
return
server_id = instance_data['server_id']
log_uploader.info("Destroying server instance . . ")
oss.deprovision_instance(server_id)
log_uploader.info("Deprovisioning ready\n")
def do_housekeep(self, token):
pass