def check_for_setup_error(self): """Check for setup error. Socket timeout set for 5 seconds to verify SOPAPI rest interface is reachable and the credentials will allow us to login. """ headers = dict(Authorization=self.get_sop_auth_header()) uri = self.sop_target + '/sopapi/clusters' try: httpclient = httplib2.Http(disable_ssl_certificate_validation=True, timeout=5) resp_headers, resp_content = httpclient.request(uri, 'GET', body='', headers=headers) response = json.loads(resp_content) if 'messages' in response: soperror = _('received error: %(code)s: %(msg)s') % { 'code': response['messages'][0]['code'], 'msg': response['messages'][0]['message'], } raise exception.SopAPIError(err=soperror) except socket.timeout: raise exception.SopAPIError( err=_('connection to SOPAPI timed out'))
def deny_access(self, context, share, access, share_server=None): """Deny access to a share. Currently only IP based access control is supported. """ if access['access_type'] != 'ip': LOG.warn(_LW('Only ip access type allowed.')) return httpclient = httplib2.Http(disable_ssl_certificate_validation=True, timeout=None) sop_share_id = self._get_share_id_by_name(httpclient, share['id']) payload = { 'action': 'delete-access-rule', 'name': '%s-%s' % (share['id'], access['access_to']), } sopuri = '/shares/' + sop_share_id headers = dict(Authorization=self.get_sop_auth_header()) uri = self.sop_target + '/sopapi' + sopuri resp_headers, resp_content = httpclient.request( uri, 'POST', body=json.dumps(payload), headers=headers) resp_code = int(resp_headers['status']) if resp_code == 202: job_loc = resp_headers['location'] self._wait_for_job_completion(httpclient, job_loc) else: raise exception.SopAPIError(err=_('received error: %s') % resp_headers['status'])
def _wait_for_job_completion(self, httpclient, job_uri): """Wait for job identified by job_uri to complete.""" count = 0 headers = dict(Authorization=self.get_sop_auth_header()) # NOTE(jasonsb): timeout logic here needs be revisited after # load testing results are in. while True: if count > 300: raise exception.SopAPIError(err=_('job timed out')) resp_headers, resp_content = httpclient.request(job_uri, 'GET', body='', headers=headers) if int(resp_headers['status']) != 200: raise exception.SopAPIError(err=_('error getting job status')) job = json.loads(resp_content) if job['properties']['completion-status'] == 'ERROR': raise exception.SopAPIError(err=_('job errored out')) if job['properties']['completion-status'] == 'COMPLETE': return job time.sleep(1) count += 1
def _delete_share_sopapi(self, httpclient, share_id): """Delete share on SOP.""" sopuri = '/shares/' + share_id headers = dict(Authorization=self.get_sop_auth_header()) uri = self.sop_target + '/sopapi' + sopuri resp_headers, resp_content = httpclient.request(uri, 'DELETE', body='', headers=headers) resp_code = int(resp_headers['status']) if resp_code == 202: job_loc = resp_headers['location'] self._wait_for_job_completion(httpclient, job_loc) else: raise exception.SopAPIError(err=_('received error: %s') % resp_headers['status'])
def allow_access(self, context, share, access, share_server=None): """Allow access to a share. Currently only IP based access control is supported. """ if access['access_type'] != 'ip': raise exception.InvalidShareAccess( reason=_('only IP access type allowed')) httpclient = httplib2.Http(disable_ssl_certificate_validation=True, timeout=None) sop_share_id = self._get_share_id_by_name(httpclient, share['id']) if access['access_level'] == 'rw': access_level = True elif access['access_level'] == 'ro': access_level = False else: raise exception.InvalidShareAccess( reason=(_('Unsupported level of access was provided - %s') % access['access_level'])) payload = { 'action': 'add-access-rule', 'all-squash': True, 'anongid': 65534, 'anonuid': 65534, 'host-specification': access['access_to'], 'description': '', 'read-write': access_level, 'root-squash': False, 'tags': 'nfs', 'name': '%s-%s' % (share['id'], access['access_to']), } sopuri = '/shares/' headers = dict(Authorization=self.get_sop_auth_header()) uri = self.sop_target + '/sopapi' + sopuri + sop_share_id resp_headers, resp_content = httpclient.request( uri, 'POST', body=json.dumps(payload), headers=headers) resp_code = int(resp_headers['status']) if resp_code == 202: job_loc = resp_headers['location'] self._wait_for_job_completion(httpclient, job_loc) else: raise exception.SopAPIError(err=_('received error: %s') % resp_headers['status'])
def _add_file_system_sopapi(self, httpclient, payload): """Add a new filesystem via SOPAPI.""" sopuri = '/file-systems/' headers = dict(Authorization=self.get_sop_auth_header()) uri = self.sop_target + '/sopapi' + sopuri payload_json = json.dumps(payload) resp_headers, resp_content = httpclient.request(uri, 'POST', body=payload_json, headers=headers) resp_code = int(resp_headers['status']) if resp_code == 202: job_loc = resp_headers['location'] self._wait_for_job_completion(httpclient, job_loc) else: raise exception.SopAPIError( err=(_('received error: %s') % resp_content['messages'][0]['message']))
def _add_share_sopapi(self, httpclient, payload): """Add a new filesystem via SOPAPI.""" sopuri = '/shares/' headers = dict(Authorization=self.get_sop_auth_header()) payload_json = json.dumps(payload) uri = self.sop_target + '/sopapi' + sopuri resp_headers, resp_content = httpclient.request(uri, 'POST', body=payload_json, headers=headers) resp_code = int(resp_headers['status']) if resp_code == 202: job_loc = resp_headers['location'] job = self._wait_for_job_completion(httpclient, job_loc) if job['properties']['completion-status'] == 'COMPLETE': return job['properties']['resource-name'] else: raise exception.SopAPIError(err=_('received error: %s') % resp_headers['status'])
def _get_share_id_by_name(self, httpclient, share_name): """Look up share given the share name.""" sopuri = '/shares/list?name=' + share_name headers = dict(Authorization=self.get_sop_auth_header()) uri = self.sop_target + '/sopapi' + sopuri resp_headers, resp_content = httpclient.request(uri, 'GET', body='', headers=headers) response = json.loads(resp_content) num_of_resources = 0 if int(resp_headers['status']) != 200 and 'messages' in response: raise exception.SopAPIError( err=(_('received error: %s') % response['messages'][0]['message'])) resource_list = response['list'] num_of_resources = len(resource_list) if num_of_resources == 0: return '' return resource_list[0]['id']