class EndPoint(): def __init__(self, user, password): self.inst = LDAP(user, password) self.inst.bind_ldap() # Retrieve information about the specified application def application_get(self, username, applicationId): try: if (not DEBUG_PERMISSIONS): user = self.inst.get_obj('cusername', username, 'openLDAPuser') if (user == None or user == ()): # User was already validated, but can't be accessed now... return json.dumps(ErrorCodes.user['unspecifiedError']) ldap_tools.parse_ldap(user) app = self.inst.get_obj('cid', applicationId, 'openLDAPapplication', True) if (app == ()): return json.dumps(ErrorCodes.user['invalidId']) ldap_tools.parse_ldap(app) if (DEBUG_PERMISSIONS): return json.dumps(app) for roleId in user['authorizedRoleIds']: role = self.inst.get_obj('cid', roleId, 'openLDAProle') if (role == None or role == ()): # Error! continue ldap_tools.parse_ldap(role) if (applicationId in role['applicationIds']): # User is authorized to access this application. return json.dumps(app) return json.dumps(ErrorCodes.user['userNotAuthorized']) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) # Retrieve data about the specified role def role_get(self, username, roleId): try: if (not DEBUG_PERMISSIONS): user = self.inst.get_obj('cusername', username, 'openLDAPuser') if (user == None or user == ()): return json.dumps(ErrorCodes.user['unspecifiedError']) ldap_tools.parse_ldap(user) role = self.inst.get_obj('cid', roleId, 'openLDAProle', True) if (role == ()): return json.dumps(ErrorCodes.user['invalidId']) ldap_tools.parse_ldap(role) if (DEBUG_PERMISSIONS or roleId in user['authorizedRoleIds']): # Now get the IP address of the virtue associated with this user/role virtue_ip = 'NULL' ldap_virtues = self.inst.get_objs_of_type('OpenLDAPvirtue') virtues = ldap_tools.parse_ldap_list(ldap_virtues) for v in virtues: if (v['username'] == username and v['roleId'] == roleId): virtue_ip = v['ipAddress'] break role['ipAddress'] = virtue_ip return json.dumps(role) return json.dumps(ErrorCodes.user['userNotAuthorized']) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) # Retrieve a list of roles available to user def user_role_list(self, username): try: user = self.inst.get_obj('cusername', username, 'openLDAPuser') if (user == None or user == ()): return json.dumps(ErrorCodes.user['unspecifiedError']) ldap_tools.parse_ldap(user) roles = [] ldap_virtues = self.inst.get_objs_of_type('OpenLDAPvirtue') virtues = ldap_tools.parse_ldap_list(ldap_virtues) for roleId in user['authorizedRoleIds']: role = self.inst.get_obj('cid', roleId, 'openLDAProle') if (role == None or role == ()): continue ldap_tools.parse_ldap(role) # Now get the IP address of the virtue associated with this user/role virtue_ip = 'NULL' for v in virtues: if (v['username'] == username and v['roleId'] == roleId): virtue_ip = v['ipAddress'] break role['ipAddress'] = virtue_ip roles.append(role) return json.dumps(roles) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) # Retrieve a list of virtues available to user def user_virtue_list(self, username): try: virtues_raw = self.inst.get_objs_of_type('OpenLDAPvirtue') if (virtues_raw == None): return json.dumps(ErrorCodes.user['unspecifiedError']) virtues_ret = [] for virtue in virtues_raw: ldap_tools.parse_ldap(virtue[1]) if (virtue[1]['username'] == username): virtues_ret.append(virtue[1]) return json.dumps(virtues_ret) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) # Retrieve information about the specified virtue def virtue_get(self, username, virtueId): try: virtue = self.inst.get_obj('cid', virtueId, 'OpenLDAPvirtue', True) if (virtue == ()): return json.dumps(ErrorCodes.user['invalidId']) ldap_tools.parse_ldap(virtue) if (virtue['username'] == username or DEBUG_PERMISSIONS): return json.dumps(virtue) return json.dumps(ErrorCodes.user['userNotAuthorized']) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) def virtue_reload_state(self, username, virtueId): try: virtue = self.inst.get_obj('cid', virtueId, 'OpenLDAPvirtue', True) if (virtue == ()): return json.dumps(ErrorCodes.user['invalidId']) ldap_tools.parse_ldap(virtue) updated_virtue = copy.deepcopy(virtue) if (virtue['username'] != username): return json.dumps(ErrorCodes.user['userNotAuthorized']) rdb_manager = RethinkDbManager() rdb_virtue = rdb_manager.get_virtue(virtueId) if (rdb_virtue == None): updated_virtue['state'] = 'STOPPED' updated_virtue['ipAddress'] = 'NULL' else: updated_virtue['state'] = 'RUNNING' updated_virtue['ipAddress'] = rdb_virtue['guestnet'] if (updated_virtue != virtue): ldap_virtue = ldap_tools.to_ldap(updated_virtue, 'OpenLDAPvirtue') self.inst.modify_obj('cid', virtueId, ldap_virtue, 'OpenLDAPvirtue', True) return json.dumps(ErrorCodes.user['success']) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) # Launch the specified virtue, which must have already been created def virtue_launch(self, username, virtueId, use_valor=True): try: virtue = self.inst.get_obj('cid', virtueId, 'OpenLDAPvirtue', True) if (virtue == ()): return json.dumps(ErrorCodes.user['invalidId']) ldap_tools.parse_ldap(virtue) if (virtue['username'] != username): return json.dumps(ErrorCodes.user['userNotAuthorized']) if ('RUNNING' in virtue['state'] or virtue['state'] == 'LAUNCHING'): return json.dumps(ErrorCodes.user['virtueAlreadyLaunched']) elif (virtue['state'] != 'STOPPED'): return json.dumps( ErrorCodes.user['virtueStateCannotBeLaunched']) if (use_valor): valor_manager = ValorManager() valor = valor_manager.get_empty_valor() try: virtue['ipAddress'] = valor_manager.add_virtue( valor['address'], valor['valor_id'], virtue['id'], 'images/provisioned_virtues/' + virtue['id'] + '.img') except AssertionError: return json.dumps(ErrorCodes.user['virtueAlreadyLaunched']) virtue['state'] = 'LAUNCHING' ldap_virtue = ldap_tools.to_ldap(virtue, 'OpenLDAPvirtue') self.inst.modify_obj('cid', virtue['id'], ldap_virtue, objectClass='OpenLDAPvirtue', throw_error=True) # wait until sshable success = False max_attempts = 5 # TODO: Remove this variable before merging into master see_no_evil = False if not use_valor: virtue['state'] = 'RUNNING' elif see_no_evil: virtue['state'] = 'RUNNING (Unverified)' else: for attempt_number in range(max_attempts): try: time.sleep(30) ssh = ssh_tool( 'virtue', virtue['ipAddress'], os.environ['HOME'] + '/user-keys/default-virtue-key.pem') ssh.ssh('echo test') print('Successfully connected to {}'.format( virtue['ipAddress'])) # KL --- add if resIDs not empty run: # Kerberos tgt setup for resource management if len(virtue['resourceIds']) is not 0: krb5cc_src = '/tmp/krb5cc_{}'.format(username) krb5cc_dest = '/tmp/krb5cc_0' ssh.scp_to(krb5cc_src, krb5cc_dest) role = self.inst.get_obj('cid', virtue['roleId'], 'openLDAProle') ldap_tools.parse_ldap(role) for res in virtue['resourceIds']: resource = self.inst.get_obj('cid', res, 'openLDAPresource') ldap_tools.parse_ldap(resource) resource_manager = ResourceManager(username, resource) getattr(resource_manager, resource['type'].lower())( virtue['ipAddress'], os.environ['HOME'] + '/user-keys/default-virtue-key.pem', role['applicationIds']) success = True break except Exception as e: print(e) print('Attempt {0} failed to connect').format(attempt_number+1) if (not success): valor_manager.rethinkdb_manager.remove_virtue(virtue['id']) virtue['state'] = 'STOPPED' ldap_virtue = ldap_tools.to_ldap(virtue, 'OpenLDAPvirtue') self.inst.modify_obj( 'cid', virtue['id'], ldap_virtue, objectClass='OpenLDAPvirtue', throw_error=True) return json.dumps(ErrorCodes.user['serverLaunchError']) virtue['state'] = 'RUNNING' ldap_virtue = ldap_tools.to_ldap(virtue, 'OpenLDAPvirtue') self.inst.modify_obj('cid', virtue['id'], ldap_virtue, objectClass='OpenLDAPvirtue', throw_error=True) return json.dumps(ErrorCodes.user['success']) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) # Stop the specified virtue, but do not destroy it def virtue_stop(self, username, virtueId, use_valor=True): try: virtue = self.inst.get_obj('cid', virtueId, 'OpenLDAPvirtue', True) if (virtue == ()): return json.dumps(ErrorCodes.user['invalidId']) ldap_tools.parse_ldap(virtue) if (virtue['username'] != username): return json.dumps(ErrorCodes.user['userNotAuthorized']) if (virtue['state'] == 'STOPPED'): return json.dumps(ErrorCodes.user['virtueAlreadyStopped']) elif ('RUNNING' not in virtue['state']): return json.dumps( ErrorCodes.user['virtueStateCannotBeStopped']) try: if (use_valor): if len(virtue['resourceIds']) is not 0: role = self.inst.get_obj('cid', virtue['roleId'], 'openLDAProle') ldap_tools.parse_ldap(role) for res in virtue['resourceIds']: resource = self.inst.get_obj('cid', res, 'openLDAPresource') ldap_tools.parse_ldap(resource) resource_manager = ResourceManager(username, resource) call = 'remove_' + resource['type'].lower() getattr(resource_manager, call)( virtue['ipAddress'], os.environ['HOME'] + '/user-keys/default-virtue-key.pem', role['applicationIds']) ssh = ssh_tool('virtue', virtue['ipAddress'], os.environ['HOME'] + \ '/user-keys/default-virtue-key.pem') ssh.ssh('sudo rm /tmp/krb5cc_0') rdb_manager = RethinkDbManager() rdb_manager.remove_virtue(virtue['id']) except AssertionError: return json.dumps(ErrorCodes.user['serverStopError']) except: print('Error:\n{}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) else: virtue['state'] = 'STOPPED' ldap_virtue = ldap_tools.to_ldap(virtue, 'OpenLDAPvirtue') self.inst.modify_obj( 'cid', virtue['id'], ldap_virtue, objectClass='OpenLDAPvirtue', throw_error=True) return json.dumps(ErrorCodes.user['success']) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) # Launch an application on the specified virtue def virtue_application_launch(self, username, virtueId, applicationId, use_ssh=True): try: virtue = self.inst.get_obj('cid', virtueId, 'OpenLDAPvirtue', True) if (virtue == ()): return json.dumps(ErrorCodes.user['invalidVirtueId']) ldap_tools.parse_ldap(virtue) if (virtue['username'] != username): return json.dumps(ErrorCodes.user['userNotAuthorized']) if ('RUNNING' not in virtue['state'] and use_ssh): return json.dumps(ErrorCodes.user['virtueNotRunning']) app = self.inst.get_obj('cid', applicationId, 'OpenLDAPapplication', True) if (app == ()): return json.dumps(ErrorCodes.user['invalidApplicationId']) ldap_tools.parse_ldap(app) role = self.inst.get_obj('cid', virtue['roleId'], 'OpenLDAProle') if (role == None or role == ()): return json.dumps(ErrorCodes.user['unspecifiedError']) ldap_tools.parse_ldap(role) if (app['id'] not in role['applicationIds']): return json.dumps(ErrorCodes.user['applicationNotInVirtue']) if (app['id'] in virtue['applicationIds']): return json.dumps( ErrorCodes.user['applicationAlreadyLaunched']) if (use_ssh): ssh = ssh_tool('virtue', virtue['ipAddress'], '{0}/user-keys/{1}.pem'.format( os.environ['HOME'], username)) start_docker_container = ('sudo docker start $(sudo docker ps' + ' -af name="{0}" -q)').format( app['id']) # Copy the network Rules file. copy_network_rules = ( 'sudo docker cp /etc/networkRules $(sudo docker ps -af' + ' name="{0}" -q):/etc/networkRules').format(app['id']) ssh.ssh(copy_network_rules) # Copy the authorized keys file auth_keys_path = '/home/virtue/.ssh/authorized_keys' copy_authorized_keys_cmd = ( 'sudo docker cp {0}' ' {1}:{0}').format(auth_keys_path, app['id']) ssh.ssh(copy_authorized_keys_cmd) docker_exit = ssh.ssh(start_docker_container, test=False, silent=True) if (docker_exit != 0): # This is an issue with docker where if the docker daemon exits # uncleanly then a system file is locked and docker start fails # with the error: # Error response from daemon: id already in use # Error: failed to start containers: # The current workaround is to issue the docker start command # twice. Tne first time it fails with the above error and the # second time it succeeds. docker_exit = ssh.ssh(start_docker_container, test=False) if (docker_exit != 0): print( "Docker start command for launching application {} Failed".format( app['id'])) return json.dumps(ErrorCodes.user['serverLaunchError']) docker_chown_cmd = ( 'sudo docker exec {0}' ' chown virtue:virtue {1}').format( app['id'], auth_keys_path) ssh.ssh(docker_chown_cmd) docker_chmod_cmd = ( 'sudo docker exec {0}' ' which chmod 600 {1}').format(app['id'], auth_keys_path) ssh.ssh(docker_chmod_cmd) virtue['applicationIds'].append(applicationId) del virtue['state'] del virtue['ipAddress'] ldap_virtue = ldap_tools.to_ldap(virtue, 'OpenLDAPvirtue') assert 0 == self.inst.modify_obj('cid', virtue['id'], ldap_virtue, objectClass='OpenLDAPvirtue', throw_error=True) return json.dumps(ErrorCodes.user['success']) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) # Stop an application on the specified virtue def virtue_application_stop(self, username, virtueId, applicationId, use_ssh=True): try: virtue = self.inst.get_obj('cid', virtueId, 'OpenLDAPvirtue', True) if (virtue == ()): return json.dumps(ErrorCodes.user['invalidVirtueId']) ldap_tools.parse_ldap(virtue) if (virtue['username'] != username): return json.dumps(ErrorCodes.user['userNotAuthorized']) if ('RUNNING' not in virtue['state'] and use_ssh): return json.dumps(ErrorCodes.user['virtueNotRunning']) app = self.inst.get_obj('cid', applicationId, 'OpenLDAPapplication', True) if (app == ()): return json.dumps(ErrorCodes.user['invalidApplicationId']) ldap_tools.parse_ldap(app) role = self.inst.get_obj('cid', virtue['roleId'], 'OpenLDAProle') if (role == None or role == ()): return json.dumps(ErrorCodes.user['unspecifiedError']) ldap_tools.parse_ldap(role) if (app['id'] not in role['applicationIds']): return json.dumps(ErrorCodes.user['applicationNotInVirtue']) if (app['id'] not in virtue['applicationIds']): return json.dumps(ErrorCodes.user['applicationAlreadyStopped']) if (use_ssh): ssh = ssh_tool('virtue', virtue['ipAddress'], '{0}/user-keys/{1}.pem'.format( os.environ['HOME'], username)) docker_exit = ssh.ssh(('sudo docker stop $(sudo docker ps -af ' 'name="{0}" -q)').format(app['id']), test=False) if (docker_exit != 0): return json.dumps(ErrorCodes.user['serverStopError']) virtue['applicationIds'].remove(applicationId) del virtue['state'] del virtue['ipAddress'] ldap_virtue = ldap_tools.to_ldap(virtue, 'OpenLDAPvirtue') assert 0 == self.inst.modify_obj('cid', virtue['id'], ldap_virtue, objectClass='OpenLDAPvirtue', throw_error=True) return json.dumps(ErrorCodes.user['success']) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) def key_get(self, username): try: with open('{0}/user-keys/{1}.pem'.format( os.environ['HOME'], username), 'r') as keyfile: data = keyfile.read() return json.dumps(data) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError'])
class EndPoint_Admin(): def __init__(self, user, password): self.inst = LDAP(user, password) self.inst.bind_ldap() self.valor_api = ValorAPI() self.rdb_manager = RethinkDbManager() def application_list(self): try: ldap_applications = self.inst.get_objs_of_type( 'OpenLDAPapplication') assert ldap_applications != None applications = ldap_tools.parse_ldap_list(ldap_applications) return json.dumps(applications) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) def resource_create(self, resource): try: resource_keys = ['credentials', 'type', 'unc'] if (set(resource.keys()) != set(resource_keys) and set(resource.keys()) != set(resource_keys + ['id'])): return json.dumps(ErrorCodes.admin['invalidFormat']) if (not isinstance(resource['credentials'], basestring) or not isinstance(resource['type'], basestring) or not isinstance(resource['unc'], basestring)): return json.dumps(ErrorCodes.admin['invalidFormat']) resource['id'] = 'Resource_{}_{}'.format(resource['type'], int(time.time())) ldap_resource = ldap_tools.to_ldap(resource, 'OpenLDAPresource') self.inst.add_obj(ldap_resource, 'resources', 'cid', throw_error=True) return json.dumps(resource) except Exception as e: return json.dumps(ErrorCodes.admin['unspecifiedError']) def resource_destroy(self, resourceId): try: resource = self.inst.get_obj('cid', resourceId, 'OpenLDAPresource', True) if (resource == ()): return json.dumps(ErrorCodes.admin['invalidId']) ldap_tools.parse_ldap(resource) # KL --- add check if in use ldap_virtues = self.inst.get_objs_of_type('OpenLDAPvirtue') virtues = ldap_tools.parse_ldap_list(ldap_virtues) if any(resourceId in virtue['resourceIds'] for virtue in virtues): return json.dumps(ErrorCodes.admin['virtueUsingResource']) self.inst.del_obj('cid', resource['id'], throw_error=True) except: print('Error while deleting {}:\n{}'.format( resource['id'], traceback.format_exc())) return json.dumps(ErrorCodes.user['serverDestroyError']) return json.dumps(ErrorCodes.admin['success']) def resource_get(self, resourceId): try: resource = self.inst.get_obj('cid', resourceId, objectClass='OpenLDAPresource', throw_error=True) if (resource == ()): return json.dumps(ErrorCodes.admin['invalidId']) ldap_tools.parse_ldap(resource) return json.dumps(resource) except Exception as e: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.admin['unspecifiedError']) def resource_list(self): try: ldap_resources = self.inst.get_objs_of_type('OpenLDAPresource') assert ldap_resources != None resources = ldap_tools.parse_ldap_list(ldap_resources) return json.dumps(resources) except Exception as e: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.admin['unspecifiedError']) def resource_attach(self, resourceId, virtueId): try: resource = self.inst.get_obj('cid', resourceId, objectClass='OpenLDAPresource', throw_error=True) if (resource == ()): return json.dumps(ErrorCodes.admin['invalidResourceId']) ldap_tools.parse_ldap(resource) virtue = self.inst.get_obj('cid', virtueId, objectClass='OpenLDAPvirtue', throw_error=True) if (virtue == ()): return json.dumps(ErrorCodes.admin['invalidVirtueId']) ldap_tools.parse_ldap(virtue) #if (virtue['state'] == 'DELETING'): # return json.dumps(ErrorCodes.admin['invalidVirtueState']) if (virtue['state'] != 'STOPPED'): return json.dumps(ErrorCodes.admin['invalidVirtueState']) if (resourceId in virtue['resourceIds']): return json.dumps(ErrorCodes.admin['cantAttach']) virtue['resourceIds'].append(resourceId) self.inst.modify_obj('cid', virtue['id'], ldap_tools.to_ldap(virtue, 'OpenLDAPvirtue'), objectClass='OpenLDAPvirtue', throw_error=True) #return json.dumps(ErrorCodes.admin['notImplemented']) return json.dumps(ErrorCodes.admin['success']) except Exception as e: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.admin['unspecifiedError']) def resource_detach(self, resourceId, virtueId): try: resource = self.inst.get_obj('cid', resourceId, objectClass='OpenLDAPresource', throw_error=True) if (resource == ()): return json.dumps(ErrorCodes.admin['invalidResourceId']) ldap_tools.parse_ldap(resource) virtue = self.inst.get_obj('cid', virtueId, objectClass='OpenLDAPvirtue', throw_error=True) if (virtue == ()): return json.dumps(ErrorCodes.admin['invalidVirtueId']) ldap_tools.parse_ldap(virtue) if (resourceId not in virtue['resourceIds']): return json.dumps(ErrorCodes.admin['cantDetach']) if (virtue['state'] != 'STOPPED'): return json.dumps(ErrorCodes.admin['invalidVirtueState']) virtue['resourceIds'].remove(resourceId) self.inst.modify_obj('cid', virtue['id'], ldap_tools.to_ldap(virtue, 'OpenLDAPvirtue'), objectClass='OpenLDAPvirtue', throw_error=True) #return json.dumps(ErrorCodes.admin['notImplemented']) return json.dumps(ErrorCodes.admin['success']) except Exception as e: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.admin['unspecifiedError']) def role_create(self, role, use_ssh=True, unity_img_name=None): try: role_keys = [ 'name', 'version', 'applicationIds', 'startingResourceIds', 'startingTransducerIds', 'networkRules' ] if (set(role.keys()) != set(role_keys) and set(role.keys()) != set(role_keys + ['id'])): return json.dumps(ErrorCodes.admin['invalidFormat']) if (not isinstance(role['name'], basestring) or not isinstance(role['version'], basestring) or type(role['applicationIds']) != list or type(role['startingResourceIds']) != list or type(role['networkRules']) != list or type(role['startingTransducerIds']) != list): return json.dumps(ErrorCodes.admin['invalidFormat']) if not role['applicationIds']: return json.dumps(ErrorCodes.admin['NoApplicationId']) default_unity_size = 3 # Measured in GB. for a in role['applicationIds']: app_test = self.inst.get_obj('cid', a, objectClass='OpenLDAPapplication', throw_error=True) if (app_test == ()): return json.dumps(ErrorCodes.admin['invalidApplicationId']) ldap_tools.parse_ldap(app_test) if (app_test['os'] == 'WINDOWS'): if (app_test['name'].startswith('Microsoft Office')): default_unity_size = default_unity_size + 7 else: default_unity_size = default_unity_size + 3 else: default_unity_size = default_unity_size + 2 for r in role['startingResourceIds']: res_test = self.inst.get_obj('cid', r, objectClass='OpenLDAPresource', throw_error=True) if (res_test == ()): return json.dumps(ErrorCodes.admin['invalidResourceId']) ldap_transducers = self.inst.get_objs_of_type('OpenLDAPtransducer') assert ldap_transducers != None all_transducers = ldap_tools.parse_ldap_list(ldap_transducers) for t in role['startingTransducerIds']: if (t not in [tr['id'] for tr in all_transducers]): return json.dumps(ErrorCodes.admin['invalidTransducerId']) new_role = copy.deepcopy(role) for t in all_transducers: if (t['startEnabled'] and t['id'] not in role['startingTransducerIds']): new_role['startingTransducerIds'].append(t['id']) new_role['id'] = '{0}{1}'.format( new_role['name'].lower().replace(' ', '_'), int(time.time())) if (unity_img_name == None): closest_fit = 0 for img in os.listdir('/mnt/efs/images/unities'): img_size = int(img.replace('GB.img', '')) if (img_size >= default_unity_size and (closest_fit == 0 or closest_fit > img_size)): closest_fit = img_size if (closest_fit != 0): unity_img_name = '{}GB'.format(closest_fit) else: return json.dumps({ 'status': 'failed', 'result': [ 17, ('Could not automatically find a usable unity' ' for this role. Please specify a unity' ' image.') ] }) if ((unity_img_name + '.img') not in os.listdir('/mnt/efs/images/unities')): return json.dumps({ 'status': 'failed', 'result': [ 17, ('Could not find a unity with the name' ' ({})').format(unity_img_name) ] }) try: # Call a controller thread to create and assemble the new image thr = AssembleRoleThread(self.inst.email, self.inst.password, new_role, unity_img_name, use_ssh=use_ssh) except AssertionError: return json.dumps(ErrorCodes.admin['storageError']) thr.start() return json.dumps({'id': new_role['id'], 'name': new_role['name']}) except Exception as e: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.admin['unspecifiedError']) # Destroy the specified role def role_destroy(self, roleId, use_nfs=True): try: role = self.inst.get_obj('cid', roleId, 'OpenLDAProle', True) if (role == ()): return json.dumps(ErrorCodes.admin['invalidId']) ldap_tools.parse_ldap(role) # Check if any virtues exist with given role virtues = self.inst.get_objs_of_type('OpenLDAPvirtue') for virtue in virtues: ldap_tools.parse_ldap(virtue[1]) if (virtue[1]['roleId'] == roleId): # A Virtue exists for this role - Unable to destroy role virtueUsingRoleError = [] virtueUsingRoleError.append({ 'Virtue using the ' 'specified role exists': virtue[1]['id'] }) virtueUsingRoleError.append( ErrorCodes.admin['virtueUsingRole']) return json.dumps(virtueUsingRoleError) # Check if any user is authorized for the given role users = self.inst.get_objs_of_type('OpenLDAPuser') for user in users: ldap_tools.parse_ldap(user[1]) if (roleId in user[1]['authorizedRoleIds']): # A User exists with this role authorized - Unable to # destroy role userUsingRoleError = [] userUsingRoleError.append({ 'User authorized for the ' 'specified role exists': user[1]['username'] }) userUsingRoleError.append( ErrorCodes.admin['userUsingRole']) return json.dumps(userUsingRoleError) try: self.inst.del_obj('cid', roleId, throw_error=True) if (use_nfs): subprocess.check_call([ 'sudo', 'rm', '/mnt/efs/images/non_provisioned_virtues/' + role['id'] + '.img' ]) # Delete the Standby virtue role image files files = os.listdir('/mnt/efs/images/provisioned_virtues/') standby_files = (file for file in files if role['id'] + '_STANDBY_VIRTUE_' in file) for standby_file in standby_files: subprocess.check_call([ 'sudo', 'rm', '/mnt/efs/images/provisioned_virtues/' + standby_file ]) except: print('Error while deleting {0}:\n{1}'.format( role['id'], traceback.format_exc())) return json.dumps(ErrorCodes.admin['roleDestroyError']) return json.dumps(ErrorCodes.admin['success']) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) def role_list(self): try: ldap_roles = self.inst.get_objs_of_type('OpenLDAProle') assert ldap_roles != None roles = ldap_tools.parse_ldap_list(ldap_roles) return json.dumps(roles) except Exception as e: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.admin['unspecifiedError']) def system_export(self): return json.dumps(ErrorCodes.admin['notImplemented']) def system_import(self, data): return json.dumps(ErrorCodes.admin['notImplemented']) def test_import_user(self, which): return json.dumps(ErrorCodes.admin['notImplemented']) def test_import_application(self, which): return json.dumps(ErrorCodes.admin['notImplemented']) def test_import_role(self, which): return json.dumps(ErrorCodes.admin['notImplemented']) def user_list(self): try: # Check AD and update user list in ldap if required update_ldap_users_from_ad() ldap_users = self.inst.get_objs_of_type('OpenLDAPuser') assert ldap_users != None users = ldap_tools.parse_ldap_list(ldap_users) return json.dumps(users) except Exception as e: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.admin['unspecifiedError']) def user_get(self, username): try: # Check AD and update user list in ldap if required update_ldap_users_from_ad() user = self.inst.get_obj('cusername', username, objectClass='OpenLDAPuser', throw_error=True) if (user == ()): return json.dumps(ErrorCodes.admin['invalidUsername']) ldap_tools.parse_ldap(user) return json.dumps(user) except Exception as e: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.admin['unspecifiedError']) def user_virtue_list(self, username): try: # Check AD and update user list in ldap if required update_ldap_users_from_ad() user = self.inst.get_obj('cusername', username, objectClass='OpenLDAPuser') if (user == ()): return json.dumps(ErrorCodes.admin['invalidUsername']) elif (user == None): return json.dumps(ErrorCodes.admin['unspecifiedError']) ep = EndPoint(self.inst.email, self.inst.password) return ep.user_virtue_list(username) except Exception as e: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.admin['unspecifiedError']) def user_role_authorize(self, username, roleId): try: # Check AD and update user list in ldap if required update_ldap_users_from_ad() user = self.inst.get_obj('cusername', username, objectClass='OpenLDAPuser', throw_error=True) if (user == ()): return json.dumps(ErrorCodes.admin['invalidUsername']) ldap_tools.parse_ldap(user) role = self.inst.get_obj('cid', roleId, objectClass='OpenLDAProle', throw_error=True) if (role == ()): if (roleId in user['authorizedRoleIds']): # The user is authorized for a nonexistent role... # Remove it from their list? pass return json.dumps(ErrorCodes.admin['invalidRoleId']) ldap_tools.parse_ldap(role) if (roleId in user['authorizedRoleIds']): return json.dumps(ErrorCodes.admin['userAlreadyAuthorized']) user['authorizedRoleIds'].append(roleId) ldap_user = ldap_tools.to_ldap(user, 'OpenLDAPuser') self.inst.modify_obj('cusername', username, ldap_user, objectClass='OpenLDAPuser', throw_error=True) return json.dumps(ErrorCodes.admin['success']) except Exception as e: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.admin['unspecifiedError']) def user_role_unauthorize(self, username, roleId): try: user = self.inst.get_obj('cusername', username, objectClass='OpenLDAPuser', throw_error=True) if (user == ()): return json.dumps(ErrorCodes.admin['invalidUsername']) ldap_tools.parse_ldap(user) role = self.inst.get_obj('cid', roleId, objectClass='OpenLDAProle', throw_error=True) if (roleId not in user['authorizedRoleIds'] and role == ()): # If the role does not exist AND the user isn't 'authorized' # for it, return error. If the user is not authorized for a # real role, return error. If the user is authorized for a # nonexistent role, the admin may be trying to clean up an error return json.dumps(ErrorCodes.admin['invalidRoleId']) elif (roleId not in user['authorizedRoleIds']): return json.dumps(ErrorCodes.admin['userNotAlreadyAuthorized']) ldap_tools.parse_ldap(role) virtues = self.inst.get_objs_of_type('OpenLDAPvirtue') for v in virtues: ldap_tools.parse_ldap(v[1]) if (v[1]['username'] == username and v[1]['roleId'] == roleId): # Todo: Check if the user is logged on return json.dumps(ErrorCodes.admin['userUsingVirtue']) for r in user['authorizedRoleIds']: if (r == roleId): user['authorizedRoleIds'].remove(r) del r ldap_user = ldap_tools.to_ldap(user, 'OpenLDAPuser') self.inst.modify_obj('cusername', username, ldap_user, objectClass='OpenLDAPuser', throw_error=True) return json.dumps(ErrorCodes.admin['success']) except Exception as e: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.admin['unspecifiedError']) # Create a virtue for the specified role, but do not launch it yet def virtue_create(self, username, roleId, use_nfs=True): try: user = None role = None resources = [] virtue_dict = {} user = self.inst.get_obj('cusername', username, 'OpenLDAPuser') if (user == None or user == ()): return json.dumps(ErrorCodes.admin['invalidUsername']) ldap_tools.parse_ldap(user) role = self.inst.get_obj('cid', roleId, 'OpenLDAProle', True) if (role == ()): return json.dumps(ErrorCodes.admin['invalidRoleId']) ldap_tools.parse_ldap(role) if (roleId not in user['authorizedRoleIds']): return json.dumps(ErrorCodes.admin['userNotAlreadyAuthorized']) if (role.get('state', 'CREATED') != 'CREATED'): return json.dumps(ErrorCodes.admin['invalidRoleState']) virtue = None curr_virtues = self.inst.get_objs_of_type('OpenLDAPvirtue') for v in curr_virtues: ldap_tools.parse_ldap(v[1]) if (v[1]['username'] == username and v[1]['roleId'] == roleId): return json.dumps( ErrorCodes.user['virtueAlreadyExistsForRole']) for rid in role['startingResourceIds']: resource = self.inst.get_obj('cid', rid, 'OpenLDAPresource', True) if (resource == ()): continue ldap_tools.parse_ldap(resource) resources.append(resource) virtue_id = 'Virtue_{0}_{1}'.format( role['name'].lower().replace(' ', '_'), int(time.time())) thr = CreateVirtueThread(self.inst.email, self.inst.password, role['id'], username, virtue_id, role=role) if (use_nfs): thr.start() else: virtue = { 'id': virtue_id, 'username': username, 'roleId': roleId, 'applicationIds': [], 'resourceIds': role['startingResourceIds'], 'transducerIds': role['startingTransducerIds'], 'networkRules': role['networkRules'], 'state': 'STOPPED', 'ipAddress': 'NULL' } ldap_virtue = ldap_tools.to_ldap(virtue, 'OpenLDAPvirtue') self.inst.add_obj(ldap_virtue, 'virtues', 'cid') # Return the whole thing # return json.dumps( virtue ) # Return a json of the id and ip address return json.dumps({'ipAddress': 'NULL', 'id': virtue_id}) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) # Destroy the specified stopped virtue def virtue_destroy(self, virtueId, use_nfs=True): try: virtue = self.inst.get_obj('cid', virtueId, 'OpenLDAPvirtue', True) if (virtue == ()): return json.dumps(ErrorCodes.admin['invalidId']) ldap_tools.parse_ldap(virtue) if (virtue['state'] != 'STOPPED'): return json.dumps(ErrorCodes.user['virtueNotStopped']) try: if (use_nfs): subprocess.check_call([ 'sudo', 'rm', '/mnt/efs/images/provisioned_virtues/' + virtue['id'] + '.img' ]) self.inst.del_obj('cid', virtue['id'], throw_error=True) except: print('Error while deleting {0}:\n{1}'.format( virtue['id'], traceback.format_exc())) return json.dumps(ErrorCodes.user['serverDestroyError']) self.rdb_manager.destroy_virtue(virtue['id']) return json.dumps(ErrorCodes.admin['success']) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) def virtue_reload_state(self, virtueId): try: virtue = self.inst.get_obj('cid', virtueId, 'OpenLDAPvirtue', True) if (virtue == ()): return json.dumps(ErrorCodes.user['invalidId']) ldap_tools.parse_ldap(virtue) updated_virtue = copy.deepcopy(virtue) rdb_manager = RethinkDbManager() rdb_virtue = rdb_manager.get_virtue(virtueId) if (rdb_virtue == None): updated_virtue['state'] = 'STOPPED' updated_virtue['ipAddress'] = 'NULL' else: updated_virtue['state'] = 'RUNNING' updated_virtue['ipAddress'] = rdb_virtue['guestnet'] if (updated_virtue != virtue): ldap_virtue = ldap_tools.to_ldap(updated_virtue, 'OpenLDAPvirtue') self.inst.modify_obj('cid', virtueId, ldap_virtue, 'OpenLDAPvirtue', True) return json.dumps(ErrorCodes.user['success']) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) def valor_create(self): try: valor_id = self.valor_api.valor_create() return json.dumps({'valor_id': valor_id}) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) def valor_launch(self, valor_id): try: valor_id = self.valor_api.valor_launch(valor_id) return json.dumps({'valor_id': valor_id}) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) def valor_stop(self, valor_id): try: valor_id = self.valor_api.valor_stop(valor_id) return json.dumps({'valor_id': valor_id}) except Exception as exception: print('Error:\n{0}'.format(traceback.format_exc())) # Virtue/s exists on this valor - Unable to stop valor return json.dumps({ 'status': 'failed', 'result': [11, exception.message] }) def valor_destroy(self, valor_id): try: valor_id = self.valor_api.valor_destroy(valor_id) return json.dumps({'valor_id': valor_id}) except Exception as exception: print('Error:\n{0}'.format(traceback.format_exc())) # Virtue/s exists on this valor - Unable to destroy valor return json.dumps({ 'status': 'failed', 'result': [11, exception.message] }) def valor_list(self): try: valors = self.valor_api.valor_list() return json.dumps(valors) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) def valor_create_pool(self, number_of_valors): try: valor_ids = self.valor_api.valor_create_pool(number_of_valors) return json.dumps({'valor_ids': valor_ids}) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) def valor_migrate_virtue(self, virtue_id, destination_valor_id): try: valor_id = self.valor_api.valor_migrate_virtue( virtue_id, destination_valor_id) return json.dumps({'valor_id': valor_id}) except Exception as exception: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps({ 'status': 'failed', 'result': [11, exception.message] }) def galahad_get_id(self): try: instance_data = AWS.get_instance_info() return json.dumps(instance_data['instance-id']) except Exception as e: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.admin['unspecifiedError']) def application_add(self, application): try: app = copy.copy(application) if (set(app.keys()) != set(['id', 'name', 'version', 'os']) and set(app.keys()) != set( ['id', 'name', 'version', 'os', 'port'])): return json.dumps(ErrorCodes.admin['invalidFormat']) if (isinstance(app.get('port'), basestring)): app['port'] = int(app['port']) if (not isinstance(app['id'], basestring) or not isinstance(app['name'], basestring) or not isinstance(app['version'], basestring) or type(app.get('port', 0)) != int): return json.dumps(ErrorCodes.admin['invalidFormat']) if (app['os'] != 'LINUX' and app['os'] != 'WINDOWS'): return json.dumps(ErrorCodes.admin['invalidFormat']) if (self.inst.get_obj('cid', app['id'], throw_error=True) != ()): return json.dumps(ErrorCodes.admin['invalidId']) ecr_auth_json = subprocess.check_output([ 'aws', 'ecr', 'get-authorization-token', '--registry-ids', '703915126451', '--output', 'json', '--region', 'us-east-2' ]) ecr_auth = json.loads(ecr_auth_json.decode()) docker_registry = ecr_auth['authorizationData'][0]['proxyEndpoint'] docker_token = ecr_auth['authorizationData'][0][ 'authorizationToken'] # Since the user is only adding the app, not creating it, make sure # the image is already in the docker repo. response = requests.get( '{0}/v2/starlab-virtue/tags/list'.format(docker_registry), headers={'Authorization': 'Basic ' + docker_token}) if ('virtue-' + app['id'] not in response.json()['tags']): return json.dumps(ErrorCodes.admin['imageNotFound']) ldap_app = ldap_tools.to_ldap(app, 'OpenLDAPapplication') ret = self.inst.add_obj(ldap_app, 'virtues', 'cid') assert ret == 0 return json.dumps(ErrorCodes.admin['success']) except Exception as e: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.admin['unspecifiedError']) def auto_migration_start(self, migration_interval=None): try: self.valor_api.auto_migration_start(migration_interval) return json.dumps(ErrorCodes.admin['success']) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) def auto_migration_stop(self): try: self.valor_api.auto_migration_stop() return json.dumps(ErrorCodes.admin['success']) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) def auto_migration_status(self): try: status, interval = self.valor_api.auto_migration_status() if status: migration_status = 'ON' return json.dumps({ 'auto_migration_status': migration_status, 'auto_migration_interval': interval }) else: migration_status = 'OFF' return json.dumps({'auto_migration_status': migration_status}) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) def virtue_introspect_start(self, virtue_id, interval=None, modules=None): try: self.rdb_manager.introspect_virtue_start(virtue_id, interval, modules) return json.dumps({'virtue_id': virtue_id}) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) def virtue_introspect_stop(self, virtue_id): try: self.rdb_manager.introspect_virtue_stop(virtue_id) return json.dumps({'virtue_id': virtue_id}) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) def virtue_introspect_start_all(self, interval=None, modules=None): try: virtues_raw = self.inst.get_objs_of_type('OpenLDAPvirtue') if (virtues_raw == None): return json.dumps(ErrorCodes.user['unspecifiedError']) for virtue in virtues_raw: ldap_tools.parse_ldap(virtue[1]) virtue_running = (virtue[1]['state'] == 'RUNNING') if virtue_running: self.rdb_manager.introspect_virtue_start( virtue[1]['id'], interval, modules) return json.dumps(ErrorCodes.admin['success']) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) def virtue_introspect_stop_all(self): try: virtues_raw = self.inst.get_objs_of_type('OpenLDAPvirtue') if (virtues_raw == None): return json.dumps(ErrorCodes.user['unspecifiedError']) for virtue in virtues_raw: ldap_tools.parse_ldap(virtue[1]) virtue_running = (virtue[1]['state'] == 'RUNNING') if virtue_running: self.rdb_manager.introspect_virtue_stop(virtue[1]['id']) return json.dumps(ErrorCodes.admin['success']) except: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.user['unspecifiedError']) def _set_introspection_ldap(self, virtueId, isEnabled): introsection_id = 'introspection' virtue = self.inst.get_obj('cid', virtueId, 'OpenLDAPvirtue', True) if virtue is None or virtue == (): return json.dumps(ErrorCodes.admin['invalidVirtueId']) ldap_tools.parse_ldap(virtue) new_t_list = json.loads(virtue['transducerIds']) if isEnabled: if introsection_id not in new_t_list: new_t_list.append(introsection_id) else: if introsection_id in new_t_list: new_t_list.remove(introsection_id) virtue['transducerIds'] = json.dumps(new_t_list) ret = self.inst.modify_obj( 'cid', virtueId, ldap_tools.to_ldap(virtue, 'OpenLDAPvirtue'), 'OpenLDAPvirtue', True) if ret != 0: return json.dumps(ErrorCodes.user['unspecifiedError']) return json.dumps(ErrorCodes.admin['success']) def _set_introspection_role(self, isEnabled): introspection_id = 'introspection' try: ldap_roles = self.inst.get_objs_of_type('OpenLDAProle') assert ldap_roles != None roles = ldap_tools.parse_ldap_list(ldap_roles) for role in roles: print(role) print(role['startingTransducerIds']) new_t_list = role['startingTransducerIds'] if isEnabled: if introspection_id not in new_t_list: new_t_list.append(introspection_id) else: if introspection_id in new_t_list: new_t_list.remove(introspection_id) role['startingTransducerIds'] = new_t_list ret = self.inst.modify_obj( 'cid', role['id'], ldap_tools.to_ldap(role, 'OpenLDAProle'), 'OpenLDAProle', True) if ret != 0: return json.dumps(ErrorCodes.user['unspecifiedError']) return True except Exception as e: print('Error:\n{0}'.format(traceback.format_exc())) return json.dumps(ErrorCodes.admin['unspecifiedError'])