from ucp.swarm.structs import generateNetwork, generateToken

import json

HTTP_SUCCESS = [200, 201, 202, 204]

conn = HttpConnection(previousDeployed.container.url,
                      previousDeployed.container.username,
                      previousDeployed.container.password)
req = HttpRequest(conn)

# Get Session Token
body = json.dumps(generateToken(previousDeployed))
resp = req.post("/id/login",
                HttpEntityBuilder.create_string_entity(body),
                contentType='application/json')
if resp.getStatus() not in HTTP_SUCCESS:
    resp.errorDump()
    raise Exception(resp)
sessionToken = json.loads(resp.getResponse())['sessionToken']

# Destroy network
resp = req.delete("/networks/%s" % previousDeployed.ucpId,
                  contentType='application/json',
                  headers={"Authorization": "Bearer %s" % sessionToken})
resp.errorDump()
if resp.getStatus() not in HTTP_SUCCESS:
    raise Exception(resp)

print "Removed network with ID %s" % previousDeployed.ucpId
class datapowerClient( object ):
   def __init__( self, url, username, password ):
      '''
      Builds a datapowerClient

      :param url: The url of the REST inteface of the Datapower device
      :param username: The username to connect to the datapower device
      :param password: The passoword to connecto to the datapwoer device
      '''
      self.url = url
      if url.endswith('/'):
         self.url = url[:-1]
      self.http_connection = HttpConnection(url, username, password)
      self.request = HttpRequest( self.http_connection, username, password)
   # End __init__

   def uploadFile( self, domain, path, fileName, fileData ):
      '''
      Upload a file to a Datapower device

      param: domain: The domain in the Datapower device where the file will be stored
      param: path: the Datapower path
      param: fileName: the file to be stored on the datapower devide
      param: fileData: the file content to be stored on the datapower devide
      '''
      uri = '/mgmt/filestore/%s/%s/%s' % ( domain, path, fileName )
      fileData64 = base64.encodestring( fileData )
      payload = '''
      {
        "file": {
                "name":"%s",
                "content":"%s"
        }
      }
      '''
      body = payload % ( fileName, fileData64 )

      
      r = self.request.put( uri, HttpEntityBuilder.create_string_entity( body ), contentType = 'application/json' )
      
      response = json.loads( r.response )
      
      return response['result']
   # End uploadFile

   def downloadFile( self, domain, path, fileName ):
      '''
      Download a file from a Datapower device
   
     
      param: domain: The domain in the Datapower device where the file will be stored
      param: path: the Datapower path
      param: file: the file to be stored on the datapower devide
      '''
      uri = '/mgmt/filestore/%s/%s/%s' % ( domain, path, fileName )
      r = self.request.get( uri, contentType = 'application/json' )
      response = json.loads(r.response)
      
      print response['_links']['self']['href']
      return base64.decodestring(response['file'])
   # End downloadFile

   def deleteFile( self, domain, path, fileName ):
      '''
      Delete a file from a Datapower device
   
      param: domain: The domain in the Datapower device where the file will be stored
      param: path: the Datapower path
      param: file: the file to be stored on the datapower devide
      '''
      uri = '/mgmt/filestore/%s/%s/%s' % ( domain, path, fileName )
      r = self.request.delete( uri, contentType = 'application/json' )
      response = json.loads(r.response)
      
      return response['result']
class MMCClient(object):
    def __init__(self, url, username, password):
        self._url = url
        if url.endswith('/'):
            self._url = url[:-1]
        self._http_connection = HttpConnection(url, username, password)
        self._request = HttpRequest(self._http_connection, username, password)

    @staticmethod
    def create_client_from_deployed(deployed):
        mmc = deployed.container.mmc
        return MMCClient(mmc.url, mmc.username, mmc.password)

    def upload_to_repository(self, app_name, version, file_name, file_path):
        parts = {'name': HttpEntityBuilder.create_string_body(app_name), 'version': HttpEntityBuilder.create_string_body(version), 'file': HttpEntityBuilder.create_file_body(file_path) }
        r = self._request.post_without_headers("/api/repository", HttpEntityBuilder.create_multipart_entity(parts))
        if not r.isSuccessful and r.status != 201:
            raise Exception("Failed to upload [%s]. Server return %s.\n%s" % (file_path, r.status, r.response))
        print "Received response after upload [%s].\n" % r.response
        return json.loads(r.response)

    def delete_deployment_by_id(self, deployment_id):
        r = self._request.delete("/api/deployments/%s" % deployment_id, contentType = 'application/json')
        if not r.isSuccessful():
            raise Exception("Failed to delete [%s]. Server return %s.\n%s" % (deployment_id, r.status, r.response))

    def get_deployment_id_by_name(self, name):
        r = self._request.get("/api/deployments", contentType = 'application/json')
        deployments = json.loads(r.response)['data']
        for d in deployments:
            if d['name'] == name:
                return d['id']
        return None

    def get_deployment_by_id(self, deployment_id):
        r = self._request.get("/api/deployments/%s" % deployment_id, contentType = 'application/json')
        if not r.isSuccessful():
            raise Exception("Failed to get deployment [%s]. Server return %s.\n%s" % (deployment_id, r.status, r.response))
        return json.loads(r.response)

    def delete_deployment(self, name):
        deployment_id = self.get_deployment_id_by_name(name)
        if deployment_id:
            self.delete_deployment_by_id(deployment_id)

    def get_application_version_id(self, name, version):
        r = self._request.get("/api/repository", contentType = 'application/json')
        if not r.isSuccessful():
            raise Exception("Failed to get application version [%s]-[%s]. Server return %s.\n%s\n" % (name, version, r.status, r.response))
        applications = json.loads(r.response)['data']
        for a in applications:
            if a['name'] == name:
                for v in a['versions']:
                    if v['name'] == version:
                        return v['id']
        return None

    def get_server_groups(self):
        r = self._request.get("/api/serverGroups", contentType = 'application/json')
        return json.loads(r.response)['data']

    def get_server_group_id(self, server_group):
        for g in self.get_server_groups():
            if g['name'] == server_group:
                return g['id']
        raise Exception("No sever group found having the name %s " % server_group)

    def get_servers_for_group(self, server_group):
        r = self._request.get("/api/servers", contentType = 'application/json')
        server_ids = set()
        servers = json.loads(r.response)['data']
        for s in servers:
            for g in s['groups']:
                if server_group == g['name']:
                    server_ids.add(s['id'])
        return [str(i) for i in server_ids]

    def get_clusters(self):
        r = self._request.get("/api/clusters", contentType = 'application/json')
        return json.loads(r.response)['data']

    def get_clusters_by_name(self, cluster_name):
        cluster_ids = set()
        for c in self.get_clusters():
            if cluster_name == c['name']:
                cluster_ids.add(c['id'])
        return [str(i) for i in cluster_ids]

    def delete_application_by_id(self, application_version_id):
        r = self._request.get("api/repository/%s" % application_version_id, contentType = 'application/json')
        if not r.isSuccessful():
            raise Exception("Failed to delete application [%s]. Server return %s.\n%s" % (application_version_id, r.status, r.response))

    def delete_application(self, application_name, version):
        application_version_id = self.get_application_version_id(application_name, version)
        if application_version_id:
            self.delete_application_by_id(application_version_id)

    def _create_deployment(self, name, cluster_ids, server_ids, version_id):
        # delete existing deployment before creating new one
        self.delete_deployment(name)
        req = {'name': name, 'clusters': cluster_ids, 'servers': server_ids, 'applications': [version_id]}
        r = self._request.post("/api/deployments", HttpEntityBuilder.create_string_entity(json.dumps(req)), contentType = 'application/json')
        if not r.isSuccessful():
            raise Exception("Failed to create deployment. Server return %s.\n%s" % (r.status, r.response))
        return json.loads(r.response)['id']

    def create_cluster_deployment(self, cluster_name, deployment_name, version_id):
        cluster_ids = self.get_clusters_by_name(cluster_name)
        if len(cluster_ids) == 0:
            raise Exception("No cluster found with name : [%s] " % cluster_name)
        return self._create_deployment(deployment_name, cluster_ids, [], version_id)

    def create_server_group_deployment(self, server_group, deployment_name, version_id):
        servers_ids = self.get_servers_for_group(server_group)
        if len(servers_ids) == 0:
            raise Exception("No server found into group : %s " % server_group)
        return self._create_deployment(deployment_name, [], servers_ids, version_id)

    def deploy_deployment_by_id(self, deployment_id):
        r = self._request.post("/api/deployments/%s/deploy" % deployment_id,HttpEntityBuilder.create_string_entity(''), contentType = 'application/json')
        if not r.isSuccessful():
            raise Exception("Failed to deploy [%s]. Server return %s.\n%s" % (deployment_id, r.status, r.response))

    def redeploy_deployment_by_id(self, deployment_id):
        r = self._request.post("/api/deployments/%s/redeploy" % deployment_id,HttpEntityBuilder.create_string_entity(''),  contentType = 'application/json')
        if not r.isSuccessful():
            raise Exception("Failed to redeploy [%s]. Server return %s.\n%s" % (deployment_id, r.status, r.response))

    def wait_for_deployment(self, deployment_id):
        status = "Unknown"
        deployment = None
        while status != "FAILED" and status != "DEPLOYED":
            deployment = self.get_deployment_by_id(deployment_id)
            status = deployment["status"]
            time.sleep(5)
        return status == "DEPLOYED", deployment
class datapowerClient(object):
    def __init__(self, url, username, password):
        '''
      Builds a datapowerClient

      :param url: The url of the REST inteface of the Datapower device
      :param username: The username to connect to the datapower device
      :param password: The passoword to connecto to the datapwoer device
      '''
        self.url = url
        if url.endswith('/'):
            self.url = url[:-1]
        self.http_connection = HttpConnection(url, username, password)
        self.request = HttpRequest(self.http_connection, username, password)

    # End __init__

    def uploadFile(self, domain, path, fileName, fileData):
        '''
      Upload a file to a Datapower device

      param: domain: The domain in the Datapower device where the file will be stored
      param: path: the Datapower path
      param: fileName: the file to be stored on the datapower devide
      param: fileData: the file content to be stored on the datapower devide
      '''
        uri = '/mgmt/filestore/%s/%s/%s' % (domain, path, fileName)
        fileData64 = base64.encodestring(fileData)
        payload = '''
      {
        "file": {
                "name":"%s",
                "content":"%s"
        }
      }
      '''
        body = payload % (fileName, fileData64)

        r = self.request.put(uri,
                             HttpEntityBuilder.create_string_entity(body),
                             contentType='application/json')

        response = json.loads(r.response)

        return response['result']

    # End uploadFile

    def downloadFile(self, domain, path, fileName):
        '''
      Download a file from a Datapower device
   
     
      param: domain: The domain in the Datapower device where the file will be stored
      param: path: the Datapower path
      param: file: the file to be stored on the datapower devide
      '''
        uri = '/mgmt/filestore/%s/%s/%s' % (domain, path, fileName)
        r = self.request.get(uri, contentType='application/json')
        response = json.loads(r.response)

        print response['_links']['self']['href']
        return base64.decodestring(response['file'])

    # End downloadFile

    def deleteFile(self, domain, path, fileName):
        '''
      Delete a file from a Datapower device
   
      param: domain: The domain in the Datapower device where the file will be stored
      param: path: the Datapower path
      param: file: the file to be stored on the datapower devide
      '''
        uri = '/mgmt/filestore/%s/%s/%s' % (domain, path, fileName)
        r = self.request.delete(uri, contentType='application/json')
        response = json.loads(r.response)

        return response['result']