class PCCEC2Connection(EC2Connection):
    logger = IaasLogger()
    useProxy = False

    def connect(self, host=None, port=None, base_url = None):
        # prefer the attribute base_url if its set or sent
        connection = None
        secure = self.secure

        if getattr(self, 'base_url', None) and base_url == None:
            (host, port, secure, self.request_path) = self._tuple_from_url(self.base_url)
        elif base_url != None:
            (host, port, secure, self.request_path) = self._tuple_from_url(base_url)
        else:
            host = host or self.host
            port = port or self.port

        kwargs = {'host': host, 'port': int(port)}

        if not self.useProxy:
            #self.logger.debug("**************** OFF PROXY !")
            connection = self.conn_classes[secure](**kwargs)
        elif proxy_port is None or proxy_port == "":
            #self.logger.debug("**************** NON PROXY !")
            connection = self.conn_classes[secure](**kwargs)
        else:
            #self.logger.debug("**************** ON PROXY !")
            connection = self.conn_classes[secure](proxy_host, proxy_port)
            if proxy_user is not None and proxy_user != "":
                 headers = {"Proxy-Authorization":"Basic " + base64.b64encode(proxy_user + ":" + proxy_pass)}
                 kwargs["headers"] = headers
            connection.set_tunnel(**kwargs)

        self.connection = connection
class PropertiesReader(dict):
    logger = IaasLogger()
    prop = re.compile(r"([\w. ]+)\s*=\s*(.*)")
    src = os.environ.get('PCC_CONFIG_HOME', "") + "/config.properties"

    def __init__(self):
        self.loadConfig()

    def loadFileData(self):
        data = ""
        try:
            file = open(self.src, 'r')
            for line in file:
                if not line.startswith("#"):
                    data = data + line
            file.close()

        except IOError:
            pass

        return data

    def loadConfig(self):
        for (key, val) in self.prop.findall(self.loadFileData()):
            self[key.strip()] = val.rstrip()
class CloudStackOtherController(object):
    logger = IaasLogger()
    client = None
    conn = None
    platforminfo = None


    def __init__(self, platforminfo, cs2iaasclient, conn):
        self.client = cs2iaasclient
        self.conn = conn
        self.platforminfo = platforminfo


    def describeSnapshot(self, snapshotId):
        snapshot = self.client.describeSnapshot(snapshotId)
        return snapshot

    def describeSnapshots(self):
        snapshots = self.client.describeSnapshots()
        return snapshots

    def createSnapshot(self, volumeNo):
        tableCSVOL = self.conn.getTable("CLOUDSTACK_VOLUME")
        csVolumes = self.conn.selectOne(tableCSVOL.select(tableCSVOL.c.VOLUME_NO==volumeNo))
        volumeId = csVolumes['VOLUME_ID']

        snapshot = self.client.createSnapshot(volumeId)

        tableCSSNP = self.conn.getTable("CLOUDSTACK_SNAPSHOT")
        sql = tableCSSNP.insert({"SNAPSHOT_NO":None,
                                "SNAPSHOT_ID":snapshot["id"],
                                "FARM_NO":csVolumes["FARM_NO"],
                                "PLATFORM_NO":csVolumes["PLATFORM_NO"],
                                "CREATE_DATE":snapshot["created"],
                                "VOLUMEID":volumeId,
                                })

        self.conn.execute(sql)
        return snapshot["id"]

    def deleteSnapshot(self, snapshotNo):
        tableCSSNP = self.conn.getTable("CLOUDSTACK_SNAPSHOT")
        csSnap = self.conn.selectOne(tableCSSNP.select(tableCSSNP.c.SNAPSHOT_NO==snapshotNo))

        self.client.deleteSnapshot(csSnap["SNAPSHOT_ID"])


    def getPasswordData(self, instanceNo):
        tableCSINS = self.conn.getTable("CLOUDSTACK_INSTANCE")
        csInstance = self.conn.selectOne(tableCSINS.select(tableCSINS.c.INSTANCE_NO==instanceNo))
        passwd = self.client.getPasswordData(csInstance["INSTANCE_ID"])
        #改行コードを抜く為改行コードでスプリット
        passwdArray = passwd.splitlines()
        rtPassword = ""
        for passline in passwdArray:
            rtPassword = rtPassword + passline

        return rtPassword
Ejemplo n.º 4
0
def iaasSelect(user, platformNo, isLb = False):
    logger = IaasLogger()
    conn = MysqlConnector(user)

    '''プラットフォームを判断しユーザー情報を取得する
    '''
    platforminfo = getPlatformProperty(platformNo)
    platformType =  platforminfo["platformType"]
    platformName =  platforminfo["platformName"]

    logger.info(u"      Platform::No[%s]::種別[%s]::名称[%s]" % (str(platformNo), platformType, platformName))

    #ユーザー取得
    userTable = conn.getTable("USER")
    userinfo = conn.selectOne(userTable.select(userTable.c.USER_NO==user))


    iaasController = None
    if platformType == "aws":
        if platformName == "eucalyptus":
            return
        #EC2 およびユーカリ
        #AWS_CERTIFICATE 取得
        certificateTable = conn.getTable("AWS_CERTIFICATE")
        certificate = conn.selectOne(certificateTable.select(and_(certificateTable.c.USER_NO==user,  certificateTable.c.PLATFORM_NO==platformNo)))
        accessInfo = {"ACCESS_ID": str(certificate["AWS_ACCESS_ID"]), "SECRET_KEY": str(certificate["AWS_SECRET_KEY"]), "USER": user, "USER_NAME": userinfo["USERNAME"]}
        iaasController = EC2Controller(conn, accessInfo, platforminfo, isLb)
    elif platformType == "vmware":
        #vmware
        pass
    elif platformType == "nifty":
        #nifty
        pass
    elif platformType == "cloudstack":
        #CloudStack
        certificateTable = conn.getTable("CLOUDSTACK_CERTIFICATE")
        certificate = conn.selectOne(certificateTable.select(and_(certificateTable.c.ACCOUNT==user, certificateTable.c.PLATFORM_NO==platformNo)))
        accessInfo = {"ACCESS_ID": str(certificate["CLOUDSTACK_ACCESS_ID"]), "SECRET_KEY": str(certificate["CLOUDSTACK_SECRET_KEY"]), "USER": user, "USER_NAME": userinfo["USERNAME"]}
        iaasController = CloudStackController(conn, accessInfo, platforminfo)
    else:
        raise IaasException("PlatformError", platformNo)

    return iaasController
Ejemplo n.º 5
0
class OpenStackOtherController(object):
    logger = IaasLogger()

    client = None
    conn = None
    platforminfo = None

    def __init__(self, platforminfo, openstackiaasclient, conn):
        self.client = openstackiaasclient
        self.conn = conn
        self.platforminfo = platforminfo
Ejemplo n.º 6
0
class AzureIaasClient:

    logger = IaasLogger()
    platformNo = None
    username = None

    sms = None

    def __init__(self, platforminfo, username, subscription, certificate,
                 conn):

        self.platformNo = platforminfo["platformNo"]
        self.username = username
        # XXX: proxyのコード

        # 証明書ファイルを作成
        # XXX: テンポラリファイルの削除をどうするか要検討
        fd = tempfile.NamedTemporaryFile(prefix='pccazurecert', delete=False)
        fd.writelines(certificate)
        fd.close()

        # 接続用オブジェクトの生成
        self.certPath = fd.name
        self.subscription = subscription
        self.sms = ServiceManagementService(subscription, self.certPath)
        self.conn = conn

    def waitAsyncOperationFinished(self, asyncOperation, flg=None):
        requestId = asyncOperation.request_id
        while True:
            # XXX: socket.error: [Errno 104] Connection reset by peer が発生したことがあるので、対処必要
            try:
                operation = self.sms.get_operation_status(requestId)
                self.logger.debug('      Asynchronous Request ID: %s, Status: %s' % \
                    (operation.id, operation.status))
                if operation.status == 'InProgress':
                    if flg == 'del':
                        time.sleep(5)
                    else:
                        time.sleep(10)
                    continue
                elif operation.status == 'Succeeded':
                    break
                else:
                    self.logger.error('%s' % (operation.error.code))
                    self.logger.error('%s' % (operation.error.message))
                    break
            except:
                self.logger.error(traceback.format_exc())
                return

        return operation.status

    def generateOSHardDiskConfig(self, mediaLink, imageName):
        return OSVirtualHardDisk(imageName, mediaLink)

    def generateLinuxConfig(self, hostName, userName, userPassword,
                            customData):
        disableSshPasswordAuthentication = False
        return LinuxConfigurationSet(hostName, userName, userPassword, \
            disableSshPasswordAuthentication, custom_data=base64.b64encode(customData))

    def generateWindowsConfig(self, hostName, userName, userPassword,
                              customData):
        resetPasswordOnFirstLogon = False
        enableAutomaticUpdates = False
        timeZone = 'Tokyo Standard Time'
        windowsConfig = WindowsConfigurationSet(hostName, userName, userPassword, \
            resetPasswordOnFirstLogon, enableAutomaticUpdates, timeZone, custom_data=base64.b64encode(customData))
        windowsConfig.domain_join = None
        return windowsConfig

    def generateNetworkConfig(self, subnetID):
        network = ConfigurationSet()
        network.configuration_set_type = 'NetworkConfiguration'
        network.subnet_names.append(subnetID)
        return network

    def getOsImage(self, imageName):
        # XXX: なぜか、WindowsAzureConflictErrorが発生することがある
        osImages = self.sms.list_os_images()
        for osImage in osImages:
            # XXX: カテゴリが"User"の場合、ストレージアカウントの考慮も必要
            if osImage.name == imageName:
                return osImage
        # 名前の一致するイメージが存在しない
        return None

    def identifyImageOsType(self, imageName):
        osImage = self.getOsImage(imageName)
        if osImage is None:
            # 名前の一致するイメージが存在しない
            return None
        return osImage.os

    def _getStorageAccountKey(self, storageAccount):
        # ストレージアカウントのキーを取得
        res = self.sms.get_storage_account_keys(storageAccount)
        return res.storage_service_keys.primary

    def _getBlobFromMediaLink(self, blobService, mediaLink):
        # コンテナ一覧を取得
        containerList = blobService.list_containers()

        for container in containerList:
            # コンテナに含まれるBlob一覧を取得
            blobList = blobService.list_blobs(container.name)
            for blob in blobList:
                # URIから、先頭のhttp*://を取り除いた文字列を比較
                if blob.url.split('://')[1] == mediaLink.split('://')[1]:
                    return (container, blob)
            else:
                return (None, None)

    def _deleteBlob(self, storageAccount, mediaLink):
        primary = self._getStorageAccountKey(storageAccount)
        # BlobServiceオブジェクトを作成
        blobService = BlobService(storageAccount, primary)

        (container, blob) = self._getBlobFromMediaLink(blobService, mediaLink)

        rs = blobService.delete_blob(container_name=container.name,
                                     blob_name=blob.name)
        try:
            updatedBlob = blobService.get_blob_properties(
                container_name=container.name, blob_name=blob.name)
        except WindowsAzureMissingResourceError as e:
            return True
        return False

    def _leaseBlob(self, storageAccount, mediaLink):
        primary = self._getStorageAccountKey(storageAccount)
        # BlobServiceオブジェクトを作成
        blobService = BlobService(storageAccount, primary)

        (container, blob) = self._getBlobFromMediaLink(blobService, mediaLink)

        prop = blob.properties

        # Lease StatusがlockedだったらBlobのリース解放を試みる
        if prop.lease_status == 'locked':
            # unlockedの時に実行すると、 azure.WindowsAzureConflictError
            res = blobService.lease_blob(container_name=container.name,
                                         blob_name=blob.name,
                                         x_ms_lease_action='break')
            # (成功すると?){}が返ってくる
            updatedBlob = blobService.get_blob_properties(
                container_name=container.name, blob_name=blob.name)

    def _existDisk(self, osHardDiskName):
        diskList = self.sms.list_disks()
        for disk in diskList:
            if disk.name == osHardDiskName:
                return True
        else:
            return False

    def _deleteDisk(self, osHardDiskName):
        self.logger.debug("Blob of OS Disk deleting...(%s)" % osHardDiskName)
        try:
            # 指定されたデータまたはオペレーティング システム ディスクをイメージ リポジトリから削除
            # ディスクに関連付けられた BLOB も削除
            asyncOperation = self.sms.delete_disk(osHardDiskName, True)
        except WindowsAzureMissingResourceError as e:
            # クラウドサービス/デプロイメントが存在しない(_ERROR_NOT_FOUND)
            self.logger.error(traceback.format_exc())
            raise IaasException("EPROCESS-000916", [osHardDiskName])
        except WindowsAzureError as e:
            # XXX: Blobがロックされている場合を想定しているが、他にもこのエラーにかかる可能性あり
            self.logger.error(traceback.format_exc())
            raise IaasException("EPROCESS-000916", [osHardDiskName])
        except Exception:
            # 予期せぬ例外
            self.logger.error(traceback.format_exc())
            raise IaasException("EPROCESS-000916", [osHardDiskName])
        else:
            operationStatus = self.waitAsyncOperationFinished(asyncOperation,
                                                              flg='del')

        if operationStatus != 'Succeeded':
            raise IaasException("EPROCESS-000916", [osHardDiskName])

        self.logger.debug("Blob of OS Disk deleted.(%s)" % osHardDiskName)
        return operationStatus

    def getOsHardDisk(self, cloudService, roleName):
        deploymentName = cloudService
        # OS Virtual Hard Diskの情報は、get_deployment_by_slotでは取得できない。get_roleを使用する。
        try:
            systemProperty = self.sms.get_role(cloudService, deploymentName,
                                               roleName)
        except WindowsAzureMissingResourceError as e:
            # クラウドサービス/デプロイメントが存在しない(_ERROR_NOT_FOUND)
            return None
        else:
            return systemProperty.os_virtual_hard_disk.disk_name

    def getMediaLink(self, cloudService, roleName):
        deploymentName = cloudService
        # OS Virtual Hard Diskの情報は、get_deployment_by_slotでは取得できない。get_roleを使用する。
        try:
            systemProperty = self.sms.get_role(cloudService, deploymentName,
                                               roleName)
        except WindowsAzureMissingResourceError as e:
            # クラウドサービス/デプロイメントが存在しない(_ERROR_NOT_FOUND)
            return None
        else:
            return systemProperty.os_virtual_hard_disk.media_link

    def getDiskNameAttachedTo(self, cloudService, roleName, lun):
        deploymentName = cloudService
        try:
            systemProperty = self.sms.get_data_disk(cloudService,
                                                    deploymentName, roleName,
                                                    lun)
        except WindowsAzureMissingResourceError as e:
            # クラウドサービス/デプロイメントが存在しない(_ERROR_NOT_FOUND)
            return None
        else:
            return systemProperty.disk_name

    def createAddDataDisk(self, cloudService, roleName, mediaLink, size, lun):
        deploymentName = cloudService
        # TODO: アタッチコンフリクト問題に暫定的に対応
        for i in range(0, 6):
            try:
                asyncOperation = self.sms.add_data_disk(service_name = cloudService, \
                deployment_name = deploymentName, role_name = roleName, \
                lun = lun, host_caching = 'ReadOnly', media_link = mediaLink, \
                disk_label = None, disk_name = None, logical_disk_size_in_gb = size, \
                #disk_label = '%sL' % (diskName), disk_name = '%sN' % (diskName), logical_disk_size_in_gb = size, \
                source_media_link = None)
            except WindowsAzureMissingResourceError as e:
                # クラウドサービス/デプロイメントが存在しない(_ERROR_NOT_FOUND)
                self.logger.error(traceback.format_exc())
                raise IaasException("EPROCESS-000915", [roleName])
            except WindowsAzureConflictError as e:
                # TODO: アタッチコンフリクト問題に暫定的に対応
                if i == 5:
                    # 既に存在する
                    self.logger.error(traceback.format_exc())
                    raise IaasException("EPROCESS-000915", [roleName])
                else:
                    time.sleep(30)
                    continue
            except Exception:
                # 予期せぬ例外
                self.logger.error(traceback.format_exc())
                raise IaasException("EPROCESS-000915", [roleName])
            else:
                operationStatus = self.waitAsyncOperationFinished(
                    asyncOperation)
            if operationStatus != 'Succeeded':
                raise IaasException("EPROCESS-000915", [roleName])

            return operationStatus

    def addDataDisk(self, cloudService, roleName, diskName, lun):
        deploymentName = cloudService
        # TODO: アタッチコンフリクト問題に暫定的に対応
        for i in range(0, 6):
            try:
                asyncOperation = self.sms.add_data_disk(service_name = cloudService, \
                deployment_name = deploymentName, role_name = roleName, \
                lun = lun, host_caching = 'ReadOnly', media_link = None, \
                disk_label = None, disk_name = diskName, logical_disk_size_in_gb = None, \
                #disk_label = '%sL' % (diskName), disk_name = '%sN' % (diskName), logical_disk_size_in_gb = size, \
                source_media_link = None)
            except WindowsAzureMissingResourceError as e:
                # クラウドサービス/デプロイメントが存在しない(_ERROR_NOT_FOUND)
                self.logger.error(traceback.format_exc())
                raise IaasException("EPROCESS-000910", [roleName, diskName])
            except WindowsAzureConflictError as e:
                # TODO: アタッチコンフリクト問題に暫定的に対応
                if i == 5:
                    # 既に存在する
                    self.logger.error(traceback.format_exc())
                    raise IaasException("EPROCESS-000910",
                                        [roleName, diskName])
                else:
                    time.sleep(30)
                    continue
            except Exception:
                # 予期せぬ例外
                self.logger.error(traceback.format_exc())
                raise IaasException("EPROCESS-000910", [roleName, diskName])
            else:
                operationStatus = self.waitAsyncOperationFinished(
                    asyncOperation)
            if operationStatus != 'Succeeded':
                raise IaasException("EPROCESS-000910", [roleName, diskName])

            return operationStatus

    def deleteDataDisk(self, cloudService, roleName, diskName, lun):
        deploymentName = cloudService
        # TODO: デタッチコンフリクト問題に暫定的に対応
        for i in range(0, 6):
            try:
                asyncOperation = self.sms.delete_data_disk(service_name = cloudService, \
                deployment_name = deploymentName, role_name = roleName, \
                lun = lun)
            except WindowsAzureMissingResourceError as e:
                # クラウドサービス/デプロイメントが存在しない(_ERROR_NOT_FOUND)
                self.logger.error(traceback.format_exc())
                raise IaasException("EPROCESS-000911", [roleName, diskName])
            except WindowsAzureConflictError as e:
                # TODO: アタッチコンフリクト問題に暫定的に対応
                if i == 5:
                    # 既に存在する
                    self.logger.error(traceback.format_exc())
                    raise IaasException("EPROCESS-000911",
                                        [roleName, diskName])
                else:
                    time.sleep(30)
                    continue
            except Exception:
                # 予期せぬ例外
                self.logger.error(traceback.format_exc())
                raise IaasException("EPROCESS-000911", [roleName, diskName])
            else:
                operationStatus = self.waitAsyncOperationFinished(
                    asyncOperation)
            if operationStatus != 'Succeeded':
                raise IaasException("EPROCESS-000911", [roleName, diskName])

            return operationStatus

    def getVirtualMachineType(self, cloudService, roleName):
        try:
            systemProperty = self.sms.get_deployment_by_slot(
                cloudService, 'production')
        except WindowsAzureMissingResourceError as e:
            # クラウドサービス/デプロイメントが存在しない(_ERROR_NOT_FOUND)
            return None
        else:
            for role in systemProperty.role_instance_list:
                if role.role_name == roleName:
                    # インスタンスが見つかったらインスタンスサイズを返す
                    return role.instance_size
            # インスタンスが見つからない場合はNoneを返す
            return None

    def getVirtualMachineIpAddress(self, cloudService, roleName):
        try:
            systemProperty = self.sms.get_deployment_by_slot(
                cloudService, 'production')
        except WindowsAzureMissingResourceError as e:
            # クラウドサービス/デプロイメントが存在しない(_ERROR_NOT_FOUND)
            return None
        else:
            for role in systemProperty.role_instance_list:
                if role.role_name == roleName:
                    # インスタンスが見つかったらステータスを返す
                    return role.ip_address
            # インスタンスが見つからない場合はNoneを返す
            return None

    def updateVirtualMachineType(self, cloudService, roleName, roleSize, networkConfig, \
                                 availabilitySet):
        deploymentName = cloudService
        try:
            asyncOperation = self.sms.update_role( \
            service_name=cloudService, deployment_name=deploymentName, \
            role_name=roleName, role_size=roleSize, network_config=networkConfig, \
            availability_set_name=availabilitySet)
        except Exception:
            # 予期せぬ例外
            self.logger.error(traceback.format_exc())
            return None
        else:
            operationStatus = self.waitAsyncOperationFinished(asyncOperation)
            # 異常系テストコード
            #operationStatus = 'Failed'
            if operationStatus != 'Succeeded':
                raise IaasException("EPROCESS-000913", [roleName])

        return roleSize

    def getVirtualMachineStatus(self, cloudService, roleName):
        # ステータスの取得に失敗した場合はNoneを返す。
        try:
            systemProperty = self.sms.get_deployment_by_slot(
                cloudService, 'production')
        except WindowsAzureMissingResourceError as e:
            # クラウドサービス/デプロイメントが存在しない(_ERROR_NOT_FOUND)
            return None
        # XXX: socket.error: [Errno 104] Connection reset by peer が発生したことがあるので、対処必要
        else:
            for role in systemProperty.role_instance_list:
                if role.role_name == roleName:
                    # インスタンスが見つかったらステータスを返す
                    return role.instance_status
            # インスタンスが見つからない場合はNoneを返す
            return None

    def waitVirtualMachineStatus(self, cloudService, roleName, expectedStatus):
        # XXX: タイムアウト実装必要
        while True:
            status = self.getVirtualMachineStatus(cloudService, roleName)
            self.logger.debug('      Virtual machine: %s, Status: %s' %
                              (roleName, status))
            if status == expectedStatus:
                return status
            elif status == 'ProvisioningFailed':
                # 失敗
                return status
            elif status is None:
                return status
            else:
                time.sleep(10)
                continue

    def waitVirtualMachineStatusStoppedVM(self, cloudService, roleName):
        return self.waitVirtualMachineStatus(cloudService, roleName,
                                             'StoppedVM')

    def waitVirtualMachineStatusReadyRole(self, cloudService, roleName):
        return self.waitVirtualMachineStatus(cloudService, roleName,
                                             'ReadyRole')

    def listVirtualMachines(self, cloudService):
        try:
            systemProperty = self.sms.get_deployment_by_slot(
                cloudService, 'production')
        except WindowsAzureMissingResourceError as e:
            # クラウドサービス/デプロイメントが存在しない(_ERROR_NOT_FOUND)
            return None
        else:
            return systemProperty.role_instance_list

    def getCloudServiceStatus(self, cloudService):
        try:
            systemProperty = self.sms.get_hosted_service_properties(
                cloudService)
        except WindowsAzureMissingResourceError as e:
            # クラウドサービスが存在しない(_ERROR_NOT_FOUND)
            return None
        else:
            # クラウドサービスが存在する場合はstatusを返す
            return systemProperty.hosted_service_properties.status

    def waitCloudServiceStatusCreated(self, cloudService):
        while True:
            status = self.getCloudServiceStatus(cloudService)
            if status == 'Creating':
                time.sleep(10)
                continue
            elif status is None:
                return None
            else:
                return status

    def createCloudService(self, cloudService, affinityGroup=None):
        cloudServiceLabel = cloudService
        cloudServiceDesc = cloudService
        try:
            # クラウドサービス作成
            res = self.sms.create_hosted_service(service_name=cloudService, \
            label=cloudServiceLabel, description=cloudServiceDesc, \
            affinity_group=affinityGroup)
            if res is not None:
                # エラー(その他)
                self.logger.error(traceback.format_exc())
                raise
        except WindowsAzureConflictError as e:
            # 既に存在する
            self.logger.error(traceback.format_exc())
        except Exception:
            # 予期せぬ例外
            self.logger.error(traceback.format_exc())
            raise
        return self.waitCloudServiceStatusCreated(cloudService)

    def getStorageAccountStatus(self, storageAccount):
        try:
            systemProperty = self.sms.get_storage_account_properties(
                storageAccount)
        except WindowsAzureMissingResourceError as e:
            # ストレージアカウントが存在しない(_ERROR_NOT_FOUND)
            return None
        else:
            # ストレージアカウントが存在する場合はstatusを返す
            return systemProperty.storage_service_properties.status

    def createStorageAccount(self, storageAccount, affinityGroup=None):
        storageAccountLabel = storageAccount
        storageAccountDesc = storageAccount
        try:
            # ストレージアカウント作成
            asyncOperation = self.sms.create_storage_account(service_name=storageAccount, \
            description=storageAccountDesc, label=storageAccountLabel, \
            affinity_group=affinityGroup)
        except WindowsAzureConflictError as e:
            # 既に存在する
            self.logger.error(traceback.format_exc())
        except Exception:
            # 予期せぬ例外
            self.logger.error(traceback.format_exc())
            raise
        else:
            operationStatus = self.waitAsyncOperationFinished(asyncOperation)
            # 異常系テストコード
            #operationStatus = 'Failed'
            if operationStatus != 'Succeeded':
                raise IaasException("EPROCESS-000917", [storageAccount])

        return self.getStorageAccountStatus(storageAccount)

    def getProductionDeploymentStatus(self, cloudService):
        try:
            systemProperty = self.sms.get_deployment_by_slot(
                cloudService, 'production')
        except WindowsAzureMissingResourceError as e:
            # クラウドサービス/デプロイメントが存在しない(_ERROR_NOT_FOUND)
            return None
        else:
            return systemProperty.status

    def createVirtualMachineDeployment(self, cloudService, instanceName, osConfig, osHardDisk, \
        instanceType, networkConfig, networkName, availabilitySet):
        deploymentName = cloudService
        deploymentLabel = deploymentName
        try:
            asyncOperation = self.sms.create_virtual_machine_deployment( \
            service_name=cloudService, deployment_name=deploymentName, \
            deployment_slot='production', label=deploymentLabel, \
            role_name=instanceName, system_config=osConfig, \
            os_virtual_hard_disk=osHardDisk, role_size=instanceType, \
            network_config=networkConfig, availability_set_name=availabilitySet, \
            virtual_network_name=networkName)
        except WindowsAzureConflictError as e:
            # 既に存在する
            self.logger.error(traceback.format_exc())
            raise IaasException("EPROCESS-000903", [instanceName])
        except Exception:
            # 予期せぬ例外
            self.logger.error(traceback.format_exc())
            raise IaasException("EPROCESS-000903", [instanceName])
        else:
            operationStatus = self.waitAsyncOperationFinished(asyncOperation)
            # 異常系テストコード
            #operationStatus = 'Failed'
            if operationStatus != 'Succeeded':
                raise IaasException("EPROCESS-000903", [instanceName])

        return self.waitVirtualMachineStatusReadyRole(cloudService,
                                                      instanceName)
        #return self.getVirtualMachineStatus(cloudService, instanceName)

    def addRole(self, cloudService, instanceName, osConfig, osHardDisk, \
        instanceType, networkConfig, networkName, availabilitySet):
        # XXX: ネットワーク名が既存デプロイメントのネットワークと一致することを確認すべきか。
        deploymentName = cloudService
        try:
            asyncOperation = self.sms.add_role( \
            service_name=cloudService, deployment_name=deploymentName, \
            role_name=instanceName, system_config=osConfig, \
            os_virtual_hard_disk=osHardDisk, role_size=instanceType, \
            network_config=networkConfig, availability_set_name=availabilitySet)
        except WindowsAzureConflictError as e:
            # 既に存在する
            self.logger.error(traceback.format_exc())
            raise IaasException("EPROCESS-000905", [instanceName])
        except Exception:
            # 予期せぬ例外
            self.logger.error(traceback.format_exc())
            raise IaasException("EPROCESS-000905", [instanceName])
        else:
            operationStatus = self.waitAsyncOperationFinished(asyncOperation)
            # 異常系テストコード
            #operationStatus = 'Failed'
            if operationStatus != 'Succeeded':
                raise IaasException("EPROCESS-000905", [instanceName])

        return self.waitVirtualMachineStatusReadyRole(cloudService,
                                                      instanceName)
        #return self.getVirtualMachineStatus(cloudService, instanceName)

    def startVirtualMachine(self, cloudService, roleName):
        # XXX: クラウドサービス名=デプロイメント名を前提
        deploymentName = cloudService
        try:
            asyncOperation = self.sms.start_role( \
            service_name=cloudService, deployment_name=deploymentName, \
            role_name=roleName)
        #except WindowsAzureConflictError as e:
        #    # 既に存在する
        #    self.logger.error(traceback.format_exc())
        except Exception:
            # 予期せぬ例外
            self.logger.error(traceback.format_exc())
            raise IaasException("EPROCESS-000905", [roleName])
        else:
            operationStatus = self.waitAsyncOperationFinished(asyncOperation)
            # 異常系テストコード
            #operationStatus = 'Failed'
            if operationStatus != 'Succeeded':
                raise IaasException("EPROCESS-000905", [roleName])

        return self.waitVirtualMachineStatusReadyRole(cloudService, roleName)

    def stopVirtualMachine(self, cloudService, roleName):
        # XXX: クラウドサービス名=デプロイメント名を前提
        deploymentName = cloudService
        try:
            asyncOperation = self.sms.shutdown_role( \
            service_name=cloudService, deployment_name=deploymentName, \
            role_name=roleName)
        #except WindowsAzureConflictError as e:
        #    # 既に存在する
        #    self.logger.error(traceback.format_exc())
        except Exception:
            # 予期せぬ例外
            self.logger.error(traceback.format_exc())
            raise IaasException("EPROCESS-000907", [roleName])
        else:
            # XXX: 非同期操作が Failed したことがあった。Failしたあと、VMの状態がStoppedVMになるまで待つのは不適切。
            # XXX: 非同期操作は Failed になったのに、最終的にVMは停止したことがあった。ただし、しばらくの間、VMのstatusはReadyRoleだった。
            operationStatus = self.waitAsyncOperationFinished(asyncOperation)
            # 異常系テストコード
            #operationStatus = 'Failed'
            if operationStatus != 'Succeeded':
                raise IaasException("EPROCESS-000907", [roleName])

        return self.waitVirtualMachineStatusStoppedVM(cloudService, roleName)

    def _deleteDeployment(self, cloudService, roleName, \
                          instanceNo, farmNo, instanceInfoInstanceName):
        deploymentName = cloudService
        try:
            # 仮想マシン、オペレーティング システム ディスク、
            # 接続されたデータ ディスク、およびディスクの元の BLOB もストレージから削除
            asyncOperation = self.sms.delete_deployment( \
            service_name=cloudService, deployment_name=deploymentName)
            # 異常系テストコード
            #raise Exception
        except Exception:
            # 予期せぬ例外
            self.logger.error(traceback.format_exc())
            self.conn.error(farmNo, None, None, instanceNo, \
                            instanceInfoInstanceName, "AzureInstanceDeleteFail",["AZURE", roleName, ''])
            raise IaasException("EPROCESS-000904", [roleName])
        else:
            operationStatus = self.waitAsyncOperationFinished(asyncOperation,
                                                              flg='del')

        return operationStatus

    def _deleteRole(self, cloudService, roleName, \
                    instanceNo, farmNo, instanceInfoInstanceName):
        deploymentName = cloudService
        try:
            # 仮想マシン、オペレーティング システム ディスク、
            # 接続されたデータ ディスク、およびディスクの元の BLOB もストレージから削除
            asyncOperation = self.sms.delete_role( \
            service_name=cloudService, deployment_name=deploymentName, \
            role_name=roleName)
            # 異常系テストコード
            #raise Exception
        except Exception:
            # 予期せぬ例外
            self.logger.error(traceback.format_exc())
            self.conn.error(farmNo, None, None, instanceNo, \
                            instanceInfoInstanceName, "AzureInstanceDeleteFail",["AZURE", roleName, ''])
            raise IaasException("EPROCESS-000904", [roleName])
        else:
            operationStatus = self.waitAsyncOperationFinished(asyncOperation,
                                                              flg='del')

        return operationStatus

    def deleteVirtualMachine(self, cloudService, instanceName, storageAccount, \
                             instanceNo, farmNo, instanceInfoInstanceName):
        mediaLink = self.getMediaLink(cloudService, instanceName)
        self.logger.debug(
            '      Virtual Machine(role or deployment) %s is going to be deleted'
            % (instanceName))
        self.logger.debug('      Media Link: %s' % (mediaLink))

        roleList = self.listVirtualMachines(cloudService)
        if roleList is None:
            return None
        if len(roleList) == 1:
            # 最後のVMなので、Delete Deploymentを使う必要あり
            status = self._deleteDeployment(cloudService, instanceName, \
                                            instanceNo, farmNo, instanceInfoInstanceName)
        else:
            status = self._deleteRole(cloudService, instanceName, \
                                      instanceNo, farmNo, instanceInfoInstanceName)
        # 異常系テストコード
        #status = 'Failed'
        if status != 'Succeeded':
            self.logger.debug('      Async job did not succeed. Status: %s' %
                              (status))
            self.conn.error(farmNo, None, None, instanceNo, \
                            instanceInfoInstanceName, "AzureInstanceDeleteFail",["AZURE", instanceName, status])
            raise IaasException("EPROCESS-000904", [instanceName])

        return status

    def createVirtualMachine(self, cloudService, instanceName, osConfig, osHardDisk, \
        instanceType, networkConfig, networkName, availabilitySet):

        deploymentStatus = self.getProductionDeploymentStatus(cloudService)
        if deploymentStatus is None:
            return self.createVirtualMachineDeployment(
                cloudService, instanceName, osConfig, osHardDisk, instanceType,
                networkConfig, networkName, availabilitySet)
        else:
            # XXX: Running以外の時の扱いを決める必要あり
            return self.addRole(cloudService, instanceName, osConfig,
                                osHardDisk, instanceType, networkConfig,
                                networkName, availabilitySet)

    def deleteDataVolume(self, storageAccount, mediaLink):
        self._leaseBlob(storageAccount, mediaLink)
        time.sleep(120)
        #XXX: 下記エラーへの対処
        #WindowsAzureError: Unknown error (Bad Request)
        #<Error xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Code>BadRequest</Code><Message>A disk with name cloud-pccdev10-azure-dev10-user01_AZURE-J02-0-201311181315360171 is currently in use by virtual machine azure-dev10-user01_AZURE-J02 running within hosted service cloud-pccdev10, deployment cloud-pccdev10.</Message></Error>

        self._deleteBlob(storageAccount, mediaLink)

        return

    def deleteOSandDataDisk(self, osHardDiskName, storageAccount, mediaLink):
        accessKeys = self.sms.get_storage_account_keys(storageAccount)
        accessKey = accessKeys.storage_service_keys.primary

        if (osHardDiskName == None):
            parameter = self.subscription + ' ' + self.certPath + ' ' + storageAccount + ' ' + accessKey + ' ' + mediaLink + ' '
        else:
            parameter = self.subscription + ' ' + self.certPath + ' ' + storageAccount + ' ' + accessKey + ' ' + mediaLink + ' ' + osHardDiskName
        dir = os.path.dirname(__file__)
        self.logger.info(
            'called deleteOSandDataDisk process. python %s/azuredeleteOSandDataDisk.py %s &'
            % (dir, parameter))
        os.system('python %s/azuredeleteOSandDataDisk.py %s &' %
                  (dir, parameter))

        return

    def listVirtualNetworkSites(self):
        try:
            networks = self.sms.list_virtual_network_sites()
        except WindowsAzureMissingResourceError as e:
            # ネットワーク情報が存在しない(_ERROR_NOT_FOUND)
            return None
        else:
            return networks
Ejemplo n.º 7
0
class CloudStackInstanceController(object):

    client = None
    conn = None
    logger = IaasLogger()
    platforminfo = None

    def __init__(self, platforminfo, ec2iaasclient, conn):
        self.client = ec2iaasclient
        self.conn = conn
        self.platforminfo = platforminfo


    def startInstance(self, instanceNo):
        #AWS_INSTANCE 取得
        tableCSINS = self.conn.getTable("CLOUDSTACK_INSTANCE")
        csInstance = self.conn.selectOne(tableCSINS.select(tableCSINS.c.INSTANCE_NO==instanceNo))

        #PCC_INSTANCE 取得
        tableINS = self.conn.getTable("INSTANCE")
        pccInstance = self.conn.selectOne(tableINS.select(tableINS.c.INSTANCE_NO==instanceNo))

        #イメージの取得  再考の余地あり
        image = getImage(pccInstance["IMAGE_NO"])

        #
        if isEmpty(csInstance["INSTANCE_ID"]):
            #インスタンスの作成
            self.run(instanceNo, csInstance, pccInstance, image)

            #winodowsなら
            if (startsWithIgnoreCase(image["os"], "windows")):
                #INSTANCE_ID取得の為、CLOUDSTACK_INSTANCE 再取得
                csInstance = self.conn.selectOne(tableCSINS.select(tableCSINS.c.INSTANCE_NO==instanceNo))
                self.client.getPasswordData(csInstance["INSTANCE_ID"])

        else:
            # インスタンスが停止中でない場合はスキップ
            if (csInstance["STATE"] != "Stopped"):
                return;
            # インスタンスの起動
            self.start(instanceNo, csInstance, pccInstance)


    def stopInstance(self, instanceNo):
        #AWS_INSTANCE 取得
        tableCSINS = self.conn.getTable("CLOUDSTACK_INSTANCE")
        csInstance = self.conn.selectOne(tableCSINS.select(tableCSINS.c.INSTANCE_NO==instanceNo))
        #PCC_INSTANCE 取得
        tableINS = self.conn.getTable("INSTANCE")
        pccInstance = self.conn.selectOne(tableINS.select(tableINS.c.INSTANCE_NO==instanceNo))

        # インスタンスIDがない場合は確認する
        if (isEmpty(csInstance["INSTANCE_ID"])):
            #起動ミス対策
            nodes = self.client.describeInstances(name = pccInstance["INSTANCE_NAME"])
            if not nodes or len(nodes) == 0:
                #インスタンスが存在しない場合
                return;

            if len(nodes) >= 1:
                #FQDNを比較する
                for node in nodes:
                    if pccInstance["FQDN"] == node.extra["displayname"]:
                        #起動をミスったインスタンスを発見した場合
                        #ID情報を更新
                        csInstance["INSTANCE_ID"] = node.id
                        sql = tableCSINS.update(tableCSINS.c.INSTANCE_NO ==csInstance["INSTANCE_NO"], values=csInstance)
                        self.conn.execute(sql)

        # インスタンスの停止
        self.stop(instanceNo, csInstance, pccInstance)



####################################################################################
#---------------------ローカル------------------------------------------------------
####################################################################################

    def run(self, instanceNo, csInstance, pccInstance, image):

        #serviceoffering名称をIDへ変換
        serviceofferings = self.client.describeServiceOfferings()
        #デフォルトは最初にHitするID
        serviceofferingid = serviceofferings[0]["id"]
        for serviceoffering in serviceofferings:
            if csInstance["INSTANCE_TYPE"] == serviceoffering["name"]:
                serviceofferingid = serviceoffering["id"]


        availabilityZone = None
        if (isNotEmpty(csInstance["ZONEID"])):
            availabilityZone = csInstance["ZONEID"]

        #任意設定はここから  必要な分増やす
        extra_args = {}
        if (isNotEmpty(csInstance["NETWORKID"])):
            extra_args["network_id"] = csInstance["NETWORKID"]

        #SecurityGroup
        securityGroups = []
        if (isNotEmpty(csInstance["SECURITYGROUP"])):
            securityGroups.append(csInstance["SECURITYGROUP"].split(","))
            extra_args["securitygroupnames"] = securityGroups

        if (isNotEmpty(csInstance["KEY_NAME"])):
            extra_args["keypair"] = csInstance["KEY_NAME"]

        #UserDataを作成
        userData = self.createUserData(instanceNo, pccInstance, csInstance)
        userData = self.makeUserData(userData)
        extra_args["userdata"] = userData
        self.logger.info("userData:"+userData)


        #イベントログ出力
        self.conn.debug(pccInstance["FARM_NO"], None, None, instanceNo, pccInstance["INSTANCE_NAME"], "CloudStackInstanceCreate",["CLOUDSTACK"])

        #インスタンスの作成
        node = self.client.runInstances(pccInstance["INSTANCE_NAME"],
                                             pccInstance["FQDN"],
                                             serviceofferingid,
                                             image["templateId"],
                                             availabilityZone,
                                             **extra_args)



        if node["state"] != "Running":
            # インスタンス作成失敗時
            raise IaasException("EPROCESS-000716", [node["id"], node["state"]])

        # ログ出力
        self.logger.info(None, "IPROCESS-100603", [node["id"],])

        # イベントログ出力
        self.conn.debug(pccInstance["FARM_NO"], None, None, instanceNo, pccInstance["INSTANCE_NAME"], "CloudStackInstanceCreateFinish",["CLOUDSTACK", node["id"]])

        # データベース更新
        table = self.conn.getTable("CLOUDSTACK_INSTANCE")
        updateDict = self.conn.selectOne(table.select(table.c.INSTANCE_NO==instanceNo))
        updateDict["INSTANCE_ID"] = node["id"]
        updateDict["ZONEID"] = node["zoneid"]
        updateDict["STATE"] = node["state"]
        updateDict["DISPLAYNAME"] = node["displayname"]
        updateDict["IPADDRESS"] = node["nic"][0]["ipaddress"]
        sql = table.update(table.c.INSTANCE_NO ==updateDict["INSTANCE_NO"], values=updateDict)
        self.conn.execute(sql)


    def start(self, instanceNo, csInstance, pccInstance):
        instanceId = csInstance["INSTANCE_ID"]

        # イベントログ出力
        self.conn.debug(pccInstance["FARM_NO"], None, None, instanceNo, pccInstance["INSTANCE_NAME"], "CloudStackInstanceStart",["CLOUDSTACK", instanceId])

        #serviceoffering名称をIDへ変換
        serviceofferings = self.client.describeServiceOfferings()
        #デフォルトは最初にHitするID
        serviceofferingid = serviceofferings[0]["id"]
        for serviceoffering in serviceofferings:
            if csInstance["INSTANCE_TYPE"] == serviceoffering["name"]:
                serviceofferingid = serviceoffering["id"]

        #serviceofferingの変更有無を確認
        node = self.client.describeInstance(instanceId)
        if  node.extra["serviceofferingid"] != serviceofferingid:
            # serviceofferingの変更
            node = self.client.changeInstance(instanceId, serviceofferingid);

        # インスタンスの起動
        node = self.client.startInstance(instanceId);

        if  node["state"] != "Running":
            # インスタンス作成失敗時
            raise IaasException("EPROCESS-000716", [instanceId, node["state"]])

        # ログ出力
        self.logger.info(None, "IPROCESS-100601", [instanceId,])

        # イベントログ出力
        self.conn.debug(pccInstance["FARM_NO"], None, None, instanceNo, pccInstance["INSTANCE_NAME"], "CloudStackInstanceStartFinish",["CLOUDSTACK", instanceId])

        # データベース更新
        table = self.conn.getTable("CLOUDSTACK_INSTANCE")
        updateDict = self.conn.selectOne(table.select(table.c.INSTANCE_NO==instanceNo))
        updateDict["ZONEID"] = node["zoneid"]
        updateDict["STATE"] = node["state"]
        updateDict["DISPLAYNAME"] = node["displayname"]
        updateDict["IPADDRESS"] = node["nic"][0]["ipaddress"]
        sql = table.update(table.c.INSTANCE_NO ==updateDict["INSTANCE_NO"], values=updateDict)
        self.conn.execute(sql)


    def stop(self, instanceNo, csInstance, pccInstance):
        instanceId = csInstance["INSTANCE_ID"]

        # イベントログ出力
        self.conn.debug(pccInstance["FARM_NO"], None, None, instanceNo, pccInstance["INSTANCE_NAME"], "CloudStackInstanceStop",["CLOUDSTACK", instanceId])

        # インスタンスの停止
        node = self.client.stopInstance(instanceId);


        if node["state"] != "Stopped":
            # インスタンス作成失敗時
            raise IaasException("EPROCESS-000718", [instanceId, node["state"]])

        # ログ出力
        self.logger.info(None, "IPROCESS-100602", [instanceId,])

        # イベントログ出力
        self.conn.debug(pccInstance["FARM_NO"], None, None, instanceNo, pccInstance["INSTANCE_NAME"], "CloudStackInstanceStopFinish",["CLOUDSTACK", instanceId])

        # データベース更新
        table = self.conn.getTable("CLOUDSTACK_INSTANCE")
        updateDict = self.conn.selectOne(table.select(table.c.INSTANCE_NO==instanceNo))
        updateDict["ZONEID"] = node["zoneid"]
        updateDict["STATE"] = node["state"]
        updateDict["DISPLAYNAME"] = node["displayname"]
        updateDict["IPADDRESS"] = node["nic"][0]["ipaddress"]
        sql = table.update(table.c.INSTANCE_NO ==updateDict["INSTANCE_NO"], values=updateDict)
        self.conn.execute(sql)



    def terminate(self, instanceId):
        #CLOUDSTACK_INSTANCE 取得
        tableCSINS = self.conn.getTable("CLOUDSTACK_INSTANCE")
        csInstance = self.conn.selectOne(tableCSINS.select(tableCSINS.c.INSTANCE_ID==instanceId))

        if isEmpty(instanceId):
            #IDが指定されていない場合はそのまま返す
            return

        # インスタンスの停止
        node = self.client.terminateInstance(instanceId)

        # ログ出力
        self.logger.info(None, "IPROCESS-100604", [instanceId,])

        # データベース更新
        csInstance["ZONEID"] = None
        csInstance["STATE"] = node["state"]
        csInstance["DISPLAYNAME"] = None
        csInstance["IPADDRESS"] = None
        sql = tableCSINS.update(tableCSINS.c.INSTANCE_NO ==csInstance["INSTANCE_NO"], values=csInstance)
        self.conn.execute(sql)


    def createUserData(self, instanceNo, pccInstance, csInstance):

        table = self.conn.getTable("FARM")
        fram = self.conn.selectOne(table.select(table.c.FARM_NO==pccInstance["FARM_NO"]))

        #UserDataを作成
        userData = {}
        #DB情報
        userData.update({"instanceName": pccInstance["INSTANCE_NAME"]})
        userData.update({"farmName": fram["FARM_NAME"]})
        # FQDN
        userData.update({"hostname": pccInstance["FQDN"]})
        #初期スクリプト情報
        userData.update({"scriptserver": getScriptProperty("script.server")})

        #DNS情報
        userData.update(self.createDnsUserData(instanceNo))

        # Puppet情報
        userData.update(self.createPuppetUserData())

        # VPN情報
        internal = self.platforminfo["internal"]
        if (internal == 0):
            userData.update(self.createVpnUserData(pccInstance))

        return userData;

    def  createDnsUserData(self,instanceNo):
        # UserDataを作成
        userData = {}
        # Primary DNSサーバ
        userData.update({"dns": getDnsProperty("dns.server")})

        # Secondry DNSサーバ
        dns2 = getDnsProperty("dns.server2")
        if (isNotEmpty(dns2)):
            userData.update({"dns2": dns2})

        # DNSドメイン
        userData.update({"dnsdomain": getDnsProperty("dns.domain")})

        return userData;

    def createPuppetUserData(self):
        # UserDataを作成
        userData = {}
        # PuppetMaster情報
        userData.update({"puppetmaster": getPuppetProperty("puppet.masterHost")})
        return userData;

    def createVpnUserData(self, pccInstance):
        # UserDataを作成
        userData = {}

        #VPN情報のユーザとパスワードをセットする
        userData.update({"vpnuser": pccInstance["FQDN"]})
        userData.update({"vpnuserpass": pccInstance["INSTANCE_CODE"]})

        # VPNサーバ情報
        userData.update({"vpnserver": getVpnProperty("vpn.server")})
        userData.update({"vpnport": getVpnProperty("vpn.port")})
        # userData.update({"vpnuser": getVpnProperty("vpn.user")})
        # userData.update({"vpnuserpass": getVpnProperty("vpn.userpass")})

        # ZIPパスワード
        userData.update({"vpnzippass": getVpnProperty("vpn.zippass")})
        
        # クライアント証明書ダウンロードURL
        userData.update({"vpnclienturl": getVpnProperty("vpn.clienturl")})

        return userData;

    def makeUserData(self, map):
        if not map or len(map) == 0:
            return None

        userdata = ''
        for key in map.keys():
            value = map[key]
            if isNotEmpty(value):
                if userdata != '':
                    userdata = userdata + ';'

                userdata = userdata + key + "=" + value

        return userdata
Ejemplo n.º 8
0
class ec2OtherController(object):
    logger = IaasLogger()
    client = None
    conn = None
    platforminfo = None

    def __init__(self, platforminfo, ec2iaasclient, conn):
        self.platforminfo = platforminfo
        self.client = ec2iaasclient
        self.conn = conn

    def describeSnapshot(self, snapshotId):
        snapshot = self.client.describeSnapshot(snapshotId)
        return snapshot

    def describeSnapshots(self):
        snapshots = self.client.describeSnapshots()
        return snapshots

    def createSnapshot(self, volumeNo):

        tableAWSVOL = self.conn.getTable("AWS_VOLUME")
        awsVolumes = self.conn.selectOne(
            tableAWSVOL.select(tableAWSVOL.c.VOLUME_NO == volumeNo))
        volumeId = awsVolumes['VOLUME_ID']

        snapshot = self.client.createSnapshot(volumeId)

        tableCSSNP = self.conn.getTable("CLOUDSTACK_SNAPSHOT")
        sql = tableCSSNP.insert({
            "SNAPSHOT_NO": None,
            "FARM_NO": awsVolumes["FARM_NO"],
            "PLATFORM_NO": awsVolumes["PLATFORM_NO"],
            "VOLUME_NO": volumeNo,
            "SNAPSHOT_ID": snapshot.snapshotId,
            "CREATE_DATE": snapshot.startTime
        })

        self.conn.execute(sql)
        return snapshot

    def deleteSnapshot(self, snapshotNo):
        tableAWSSNP = self.conn.getTable("CLOUDSTACK_SNAPSHOT")
        awsSnap = self.conn.selectOne(
            tableAWSSNP.select(tableAWSSNP.c.SNAPSHOT_NO == snapshotNo))

        self.client.deleteSnapshot(awsSnap["SNAPSHOT_ID"])

    def getPasswordData(self, instanceNo):
        tableAWSINS = self.conn.getTable("AWS_INSTANCE")
        awsInstance = self.conn.selectOne(
            tableAWSINS.select(tableAWSINS.c.INSTANCE_NO == instanceNo))

        passwd = self.client.getPasswordData(awsInstance["INSTANCE_ID"])
        #前後の改行コードを抜く為改行コードでスプリット
        passwdArray = passwd.splitlines()
        #1つ目が空白になるので2つめを使う
        if passwdArray[0] == '':
            passwd = passwdArray[1]
        else:
            passwd = passwdArray[0]
        return passwd
class EC2LBConnectionUSE(ConnectionUserAndKey):
    logger = IaasLogger()
    responseCls = EC2Response
    useProxy = False
    host = LBHOSTS["US_EAST"]

    def __init__(self, user_id, key, secure=True, host=None, port=None, url=None):
        super(EC2LBConnectionUSE, self).__init__(user_id, key, secure=secure, host=host, port=port, url=url)

    def connect(self, host=None, port=None, base_url = None):
        # prefer the attribute base_url if its set or sent
        connection = None
        secure = self.secure

        if getattr(self, 'base_url', None) and base_url == None:
            (host, port, secure, self.request_path) = self._tuple_from_url(self.base_url)
        elif base_url != None:
            (host, port, secure, self.request_path) = self._tuple_from_url(base_url)
        else:
            host = host or self.host
            port = port or self.port

        kwargs = {'host': host, 'port': int(port)}

        if not self.useProxy:
            #self.logger.debug("**************** OFF PROXY !")
            connection = self.conn_classes[secure](**kwargs)
        elif proxy_port is None or proxy_port == "":
            #self.logger.debug("**************** NON PROXY !")
            connection = self.conn_classes[secure](**kwargs)
        else:
            #self.logger.debug("**************** ON PROXY !")
            connection = self.conn_classes[secure](proxy_host, proxy_port)
            if proxy_user is not None and proxy_user != "":
                 headers = {"Proxy-Authorization":"Basic " + base64.b64encode(proxy_user + ":" + proxy_pass)}
                 kwargs["headers"] = headers
            connection.set_tunnel(**kwargs)

        self.connection = connection

    def add_default_params(self, params):
        params['SignatureVersion'] = '2'
        params['SignatureMethod'] = 'HmacSHA1'
        params['AWSAccessKeyId'] = self.user_id
        params['Version'] = API_VERSION
        params['Timestamp'] = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
        params['Signature'] = self._get_aws_auth_param(params, self.key, self.action)
        return params

    def _get_aws_auth_param(self, params, secret_key, path='/'):
        keys = params.keys()
        keys.sort()
        pairs = []
        for key in keys:
            pairs.append(urllib.quote(key, safe='') + '=' +
                         urllib.quote(params[key], safe='-_~'))

        qs = '&'.join(pairs)
        string_to_sign = '\n'.join(('GET', self.host, path, qs))

        b64_hmac = base64.b64encode(
            hmac.new(secret_key, string_to_sign, digestmod=sha1).digest()
        )
        return b64_hmac
Ejemplo n.º 10
0
class VCloudInstanceController(object):

    client = None
    conn = None
    logger = IaasLogger()
    platforminfo = None

    def __init__(self, platforminfo, vciaasclient, conn):
        self.client = vciaasclient
        self.conn = conn
        self.platforminfo = platforminfo

    def startInstance(self, instanceNo):
        #AWS_INSTANCE 取得
        tableVCINS = self.conn.getTable("VCLOUD_INSTANCE")
        vcInstance = self.conn.selectOne(
            tableVCINS.select(tableVCINS.c.INSTANCE_NO == instanceNo))

        #PCC_INSTANCE 取得
        tableINS = self.conn.getTable("INSTANCE")
        pccInstance = self.conn.selectOne(
            tableINS.select(tableINS.c.INSTANCE_NO == instanceNo))

        #FARM 取得
        tableFarm = self.conn.getTable("FARM")
        farm = self.conn.selectOne(
            tableFarm.select(tableFarm.c.FARM_NO == pccInstance["FARM_NO"]))

        #組織
        vdc = self.client.getUseVdc()
        #マイクラウド
        vApp = self.client.describeMyCloud(vdc, farm["FARM_NAME"])

        #イメージの取得  再考の余地あり
        image = getImage(pccInstance["IMAGE_NO"])

        #既存VM検索
        vm = self.client.describeInstance(vApp, vcInstance["VM_NAME"])

        #VMが既に存在する場合はStart なければClone
        if vm is None:
            #インスタンスの作成
            vm = self.cloneVM(vdc, vApp, image, vcInstance, pccInstance)

            #最新情報を取得
            vcInstance = self.conn.selectOne(
                tableVCINS.select(tableVCINS.c.INSTANCE_NO == instanceNo))

            #インスタンスの起動
            self.start(vdc, vApp, vm, vcInstance, pccInstance)

            #winodowsなら
            #if (startsWithIgnoreCase(image["os"], "windows")):
            #    self.client.getPasswordData(vcInstance["INSTANCE_ID"])

        else:
            # インスタンスが停止中でない場合はスキップ
            if (vcInstance["STATUS"] != VCloudIaasClient.STOPPED):
                return

            # インスタンスの起動
            self.start(vdc, vApp, vm, vcInstance, pccInstance)

    def stopInstance(self, instanceNo):
        #AWS_INSTANCE 取得
        tableVCINS = self.conn.getTable("VCLOUD_INSTANCE")
        vcInstance = self.conn.selectOne(
            tableVCINS.select(tableVCINS.c.INSTANCE_NO == instanceNo))
        #PCC_INSTANCE 取得
        tableINS = self.conn.getTable("INSTANCE")
        pccInstance = self.conn.selectOne(
            tableINS.select(tableINS.c.INSTANCE_NO == instanceNo))
        #FARM 取得
        tableFarm = self.conn.getTable("FARM")
        farm = self.conn.selectOne(
            tableFarm.select(tableFarm.c.FARM_NO == pccInstance["FARM_NO"]))

        #組織
        vdc = self.client.getUseVdc()
        #マイクラウド
        vApp = self.client.describeMyCloud(vdc, farm["FARM_NAME"])
        #既存VM検索
        vm = self.client.describeInstance(vApp, vcInstance["VM_NAME"])
        # インスタンスが存在しない場合は何もしない
        if vm is None:
            return

        # インスタンスの停止
        self.stop(vApp, vm, vcInstance, pccInstance)

####################################################################################

    def cloneVM(self, vdc, vApp, image, vcInstance, pccInstance):

        #イベントログ出力
        platformTable = self.conn.getTable("PLATFORM")
        platform = self.conn.selectOne(
            platformTable.select(
                platformTable.c.PLATFORM_NO == pccInstance["PLATFORM_NO"]))
        self.conn.debug(
            pccInstance["FARM_NO"], None, None, pccInstance["INSTANCE_NO"],
            pccInstance["INSTANCE_NAME"], "VCloudInstanceCreate",
            [platform["PLATFORM_NAME"], pccInstance["INSTANCE_NAME"]])

        tableIN = self.conn.getTable("VCLOUD_INSTANCE_NETWORK")
        instanceNW = self.conn.select(
            tableIN.select(tableIN.c.INSTANCE_NO == vcInstance["INSTANCE_NO"]))

        tableStorage = self.conn.getTable("PLATFORM_VCLOUD_STORAGE_TYPE")
        storage = self.conn.selectOne(
            tableStorage.select(tableStorage.c.STORAGE_TYPE_NO ==
                                vcInstance["STORAGE_TYPE_NO"]))

        #イメージリンク
        imageHarf = self.client.describeImageHref(image["templateName"])

        #VAPPネットワークのアップデート確認
        self.client.checkNetwork(vApp, instanceNW)
        #ネットワーク設定 INDEX「0」にはPCCネットワークが入る為ダミーを設定
        useNetworks = [
            PccVMNetwork("", "", "", 0, 0),
        ]
        for net in instanceNW:
            #PCCネットワーク
            if getOtherProperty("vCloud.PCCNetwork") == net["NETWORK_NAME"]:
                useNetworks[0] = PccVMNetwork(net["NETWORK_NAME"],
                                              net["IP_ADDRESS"],
                                              net["IP_MODE"], 0,
                                              net["IS_PRIMARY"])
            else:
                useNetworks.append(
                    PccVMNetwork(net["NETWORK_NAME"], net["IP_ADDRESS"],
                                 net["IP_MODE"], net["NETWORK_INDEX"],
                                 net["IS_PRIMARY"]))

        #ストレージ
        storageProfile = self.client.describeStorageProfile(
            vdc, storage["STORAGE_TYPE_NAME"])

        #パラメータ作成
        info = {
            "image": imageHarf,
            "vm_name": pccInstance["INSTANCE_NAME"],
            "vm_storage": storageProfile,
            "vm_networks": useNetworks,
            "fqdn": pccInstance["FQDN"]
        }

        #仮想マシンを作成
        node = self.client.createInstances(vApp, **info)
        vm = self.client.describeInstance(node, pccInstance["INSTANCE_NAME"])
        self.logger.info(vm)
        #イベントログ出力
        self.conn.debug(
            pccInstance["FARM_NO"], None, None, pccInstance["INSTANCE_NO"],
            pccInstance["INSTANCE_NAME"], "VCloudInstanceCreateFinish",
            [platform["PLATFORM_NAME"], pccInstance["INSTANCE_NAME"]])

        #データベース更新
        tableVCINS = self.conn.getTable("VCLOUD_INSTANCE")
        updateDict = self.conn.selectOne(
            tableVCINS.select(
                tableVCINS.c.INSTANCE_NO == pccInstance["INSTANCE_NO"]))
        updateDict["VM_NAME"] = vm["name"]
        updateDict["STATUS"] = vm["state"]
        publicIp = vm["public_ips"]
        privateIp = vm["private_ips"]
        if len(publicIp) > 0:
            updateDict["IP_ADDRESS"] = publicIp[0]
        if len(privateIp) > 0:
            updateDict["PRIVATE_IP_ADDRESS"] = privateIp[0]
        else:
            updateDict["PRIVATE_IP_ADDRESS"] = updateDict["IP_ADDRESS"]

        sql = tableVCINS.update(
            tableVCINS.c.INSTANCE_NO == updateDict["INSTANCE_NO"],
            values=updateDict)
        self.conn.execute(sql)

        # TODO ここでネットーワークインデックスを更新
        self.reflectVMNetwork(vm, pccInstance["INSTANCE_NO"])

        return vm

    def start(self, vdc, vApp, vm, vcInstance, pccInstance):
        #プラットフォーム
        platformTable = self.conn.getTable("PLATFORM")
        platform = self.conn.selectOne(
            platformTable.select(
                platformTable.c.PLATFORM_NO == pccInstance["PLATFORM_NO"]))

        tableIN = self.conn.getTable("VCLOUD_INSTANCE_NETWORK")
        instanceNw = self.conn.select(
            tableIN.select(tableIN.c.INSTANCE_NO == vcInstance["INSTANCE_NO"]))

        tableStorage = self.conn.getTable("PLATFORM_VCLOUD_STORAGE_TYPE")
        storage = self.conn.selectOne(
            tableStorage.select(tableStorage.c.STORAGE_TYPE_NO ==
                                vcInstance["STORAGE_TYPE_NO"]))

        # イベントログ出力
        self.conn.debug(
            pccInstance["FARM_NO"], None, None, pccInstance["INSTANCE_NO"],
            pccInstance["INSTANCE_NAME"], "VCloudInstanceStart",
            [platform["PLATFORM_NAME"], pccInstance["INSTANCE_NAME"]])

        #インスタンスタイプの取得
        tableType = self.conn.getTable("PLATFORM_VCLOUD_INSTANCE_TYPE")
        instype = self.conn.selectOne(
            tableType.select(
                and_(
                    tableType.c.INSTANCE_TYPE_NAME ==
                    vcInstance["INSTANCE_TYPE"],
                    tableType.c.PLATFORM_NO == pccInstance["PLATFORM_NO"])))
        #現状を取得
        setCpu = self.client.describeCPU(vm)
        setMemory = self.client.describeMemory(vm)

        #変更が有れば通知
        if str(instype["CPU"]) != str(setCpu):
            self.client._change_vm_cpu(vm["id"], instype["CPU"])
        if str(instype["MEMORY"]) != str(setMemory):
            self.client._change_vm_memory(vm["id"], instype["MEMORY"])

        #ストレージ変更
        if storage["STORAGE_TYPE_NAME"] != vm["storageprofile"]:
            #変更後のストレージプロファイル
            storageProfile = self.client.describeStorageProfile(
                vdc, storage["STORAGE_TYPE_NAME"])
            self.client.editInstance(vm, **{"storageProfile": storageProfile})

        #VAPPネットワークのアップデート確認
        self.client.checkNetwork(vApp, instanceNw)
        #IPアドレスの再設定
        self.client._change_vm_nw(vm["id"], instanceNw)

        #UserDataを作成
        userData = self.createUserData(pccInstance["INSTANCE_NO"], pccInstance,
                                       vcInstance)
        #PCCネットワークGWを設定
        vappnw = self.client.describeVappNetwork(vApp)
        for net in vappnw:
            if net.name == getOtherProperty("vCloud.PCCNetwork"):
                userData.update({"pccgateway": net.gateway})
                #ルーティングIP
                userData.update(self.createUserNetwork())

        #UserDataを整形
        userData = self.makeUserData(userData)

        #UserDataのキー とりあえず固定(VMWareと同一の物)
        key = "guestinfo.userdata"

        metadata = VCloudMetadataSet(key=key, value=userData)
        metadatas = [
            metadata,
        ]
        #ユーザーデータ登録
        self.client.setProductSections(vm, metadatas)

        # VCLOUD上のステータスを確認インスタンスが停止中
        startvm = None
        if (vm["state"] == VCloudIaasClient.STOPPED):
            # インスタンスの起動
            node = self.client.startInstance(vApp, vm)
            startvm = self.client.describeInstance(node, vcInstance["VM_NAME"])
        else:
            #既にスタートしている
            startvm = vm

        #イベントログ出力
        self.conn.debug(
            pccInstance["FARM_NO"], None, None, pccInstance["INSTANCE_NO"],
            pccInstance["INSTANCE_NAME"], "VCloudInstanceStartFinish",
            [platform["PLATFORM_NAME"], pccInstance["INSTANCE_NAME"]])

        # データベース更新
        table = self.conn.getTable("VCLOUD_INSTANCE")
        updateDict = self.conn.selectOne(
            table.select(table.c.INSTANCE_NO == pccInstance["INSTANCE_NO"]))
        updateDict["STATUS"] = startvm["state"]
        publicIp = startvm["public_ips"]
        privateIp = startvm["private_ips"]
        if len(publicIp) > 0:
            updateDict["IP_ADDRESS"] = publicIp[0]
        if len(privateIp) > 0:
            updateDict["PRIVATE_IP_ADDRESS"] = privateIp[0]
        else:
            updateDict["PRIVATE_IP_ADDRESS"] = updateDict["IP_ADDRESS"]
        sql = table.update(table.c.INSTANCE_NO == updateDict["INSTANCE_NO"],
                           values=updateDict)
        self.conn.execute(sql)

        # TODO ここでネットーワークインデックス等を更新
        self.reflectVMNetwork(vm, pccInstance["INSTANCE_NO"])

    def stop(self, vApp, vm, vcInstance, pccInstance):
        #プラットフォーム
        platformTable = self.conn.getTable("PLATFORM")
        platform = self.conn.selectOne(
            platformTable.select(
                platformTable.c.PLATFORM_NO == pccInstance["PLATFORM_NO"]))

        # イベントログ出力
        self.conn.debug(
            pccInstance["FARM_NO"], None, None, pccInstance["INSTANCE_NO"],
            pccInstance["INSTANCE_NAME"], "VCloudInstanceStop",
            [platform["PLATFORM_NAME"], pccInstance["INSTANCE_NAME"]])

        # VCLOUD上のステータスを確認インスタンスが実行中
        stopvm = None
        if (vm["state"] == VCloudIaasClient.RUNNING):
            # インスタンスの停止
            node = self.client.stopInstance(vApp, vm)
            stopvm = self.client.describeInstance(node, vcInstance["VM_NAME"])
        else:
            stopvm = vm

        if stopvm["state"] != VCloudIaasClient.STOPPED:
            # インスタンス停止失敗時
            raise IaasException("EPROCESS-000718",
                                [vcInstance["VM_NAME"], stopvm["state"]])

        # イベントログ出力
        self.conn.debug(
            pccInstance["FARM_NO"], None, None, pccInstance["INSTANCE_NO"],
            pccInstance["INSTANCE_NAME"], "VCloudInstanceStopFinish",
            [platform["PLATFORM_NAME"], pccInstance["INSTANCE_NAME"]])

        # データベース更新
        table = self.conn.getTable("VCLOUD_INSTANCE")
        updateDict = self.conn.selectOne(
            table.select(table.c.INSTANCE_NO == pccInstance["INSTANCE_NO"]))
        updateDict["STATUS"] = stopvm["state"]
        sql = table.update(table.c.INSTANCE_NO == updateDict["INSTANCE_NO"],
                           values=updateDict)
        self.conn.execute(sql)

    def terminate(self, vm_name):
        #vCloud_INSTANCE 取得
        tableVCINS = self.conn.getTable("VCLOUD_INSTANCE")
        vcInstance = self.conn.selectOne(
            tableVCINS.select(tableVCINS.c.VM_NAME == vm_name))
        #PCC_INSTANCE 取得
        tableINS = self.conn.getTable("INSTANCE")
        pccInstance = self.conn.selectOne(
            tableINS.select(
                tableINS.c.INSTANCE_NO == vcInstance["INSTANCE_NO"]))
        #FARM 取得
        tableFarm = self.conn.getTable("FARM")
        farm = self.conn.selectOne(
            tableFarm.select(tableFarm.c.FARM_NO == pccInstance["FARM_NO"]))
        #プラットフォーム
        platformTable = self.conn.getTable("PLATFORM")
        platform = self.conn.selectOne(
            platformTable.select(
                platformTable.c.PLATFORM_NO == pccInstance["PLATFORM_NO"]))

        # イベントログ出力
        self.conn.debug(
            pccInstance["FARM_NO"], None, None, pccInstance["INSTANCE_NO"],
            pccInstance["INSTANCE_NAME"], "VCloudInstanceDelete",
            [platform["PLATFORM_NAME"], pccInstance["INSTANCE_NAME"]])

        #組織
        vdc = self.client.getUseVdc()
        #マイクラウド
        vApp = self.client.describeMyCloud(vdc, farm["FARM_NAME"])
        #既存VM検索
        vm = self.client.describeInstance(vApp, vcInstance["VM_NAME"])

        if vm is None:
            #存在しない場合はそのまま返す
            return

        # インスタンスの削除
        self.client.terminateInstance(vApp, vcInstance["VM_NAME"])

        # データベース更新は不要?

        # イベントログ出力
        self.conn.debug(
            pccInstance["FARM_NO"], None, None, pccInstance["INSTANCE_NO"],
            pccInstance["INSTANCE_NAME"], "VCloudInstanceDeleteFinish",
            [platform["PLATFORM_NAME"], pccInstance["INSTANCE_NAME"]])

    def reflectVMNetwork(self, vm, instanceNo):
        tableIN = self.conn.getTable("VCLOUD_INSTANCE_NETWORK")
        instanceNW = self.conn.select(
            tableIN.select(tableIN.c.INSTANCE_NO == instanceNo))

        vmNetworks = self.client.describeVMNetwork(vm)

        #既存ネットワークの更新
        for net in instanceNW:
            for vmNet in vmNetworks:
                if vmNet.name == net["NETWORK_NAME"] and vmNet.index == str(
                        net["NETWORK_INDEX"]):
                    net["IP_MODE"] = vmNet.ipMode
                    net["IP_ADDRESS"] = vmNet.ipAddress
                    if vmNet.isPrimary:
                        net["IS_PRIMARY"] = 1
                    else:
                        net["IS_PRIMARY"] = 0
                    sql = tableIN.update(
                        tableIN.c.NETWORK_NO == net["NETWORK_NO"], values=net)
                    self.conn.execute(sql)
                    vmNetworks.remove(vmNet)
                    break

        #新規ネットワークの更新 上記で残ったネットワークを使う
        for net in instanceNW:
            if net["NETWORK_INDEX"] is None:
                for vmNet in vmNetworks:
                    if vmNet.name == net["NETWORK_NAME"]:
                        net["IP_MODE"] = vmNet.ipMode
                        net["IP_ADDRESS"] = vmNet.ipAddress
                        net["NETWORK_INDEX"] = vmNet.index
                        if vmNet.isPrimary:
                            net["IS_PRIMARY"] = 1
                        else:
                            net["IS_PRIMARY"] = 0
                        sql = tableIN.update(
                            tableIN.c.NETWORK_NO == net["NETWORK_NO"],
                            values=net)
                        self.conn.execute(sql)
                        vmNetworks.remove(vmNet)
                        break

    def createUserNetwork(self):
        # UserDataを作成
        userData = {}
        zabbixserver = getOtherProperty("zabbix.server")
        if (isNotEmpty(zabbixserver)):
            #Zabbixサーバー(ルーティング用)
            userData.update({"zabbixserver": zabbixserver})

        routeAddserver = getOtherProperty("vCloud.routeAddserver")
        if (isNotEmpty(routeAddserver)):
            #ユーザー指定ルーティングサーバ
            userData.update({"routeAddserver": routeAddserver})

        return userData

    def createUserData(self, instanceNo, pccInstance, vcInstance):

        table = self.conn.getTable("FARM")
        fram = self.conn.selectOne(
            table.select(table.c.FARM_NO == pccInstance["FARM_NO"]))

        #UserDataを作成
        userData = {}
        #DB情報
        userData.update({"instanceName": pccInstance["INSTANCE_NAME"]})
        userData.update({"farmName": fram["FARM_NAME"]})
        # FQDN
        userData.update({"hostname": pccInstance["FQDN"]})
        #初期スクリプト情報
        userData.update({"scriptserver": getScriptProperty("script.server")})

        #DNS情報
        userData.update(self.createDnsUserData(instanceNo))

        # Puppet情報
        userData.update(self.createPuppetUserData())

        # VPN情報
        internal = self.platforminfo["internal"]
        if (internal == 0):
            userData.update(self.createVpnUserData(pccInstance))

        # SSHキー
        userData.update(self.createSshUserData(vcInstance))

        return userData

    def createDnsUserData(self, instanceNo):
        # UserDataを作成
        userData = {}
        # Primary DNSサーバ
        userData.update({"dns": getDnsProperty("dns.server")})

        # Secondry DNSサーバ
        dns2 = getDnsProperty("dns.server2")
        if (isNotEmpty(dns2)):
            userData.update({"dns2": dns2})

        # DNSドメイン
        userData.update({"dnsdomain": getDnsProperty("dns.domain")})

        return userData

    def createPuppetUserData(self):
        # UserDataを作成
        userData = {}
        # PuppetMaster情報
        userData.update(
            {"puppetmaster": getPuppetProperty("puppet.masterHost")})
        return userData

    def createVpnUserData(self, pccInstance):
        # UserDataを作成
        userData = {}

        #VPN情報のユーザとパスワードをセットする
        userData.update({"vpnuser": pccInstance["FQDN"]})
        userData.update({"vpnuserpass": pccInstance["INSTANCE_CODE"]})

        # VPNサーバ情報
        userData.update({"vpnserver": getVpnProperty("vpn.server")})
        userData.update({"vpnport": getVpnProperty("vpn.port")})
        # userData.update({"vpnuser": getVpnProperty("vpn.user")})
        # userData.update({"vpnuserpass": getVpnProperty("vpn.userpass")})

        # ZIPパスワード
        userData.update({"vpnzippass": getVpnProperty("vpn.zippass")})

        # クライアント証明書ダウンロードURL
        userData.update({"vpnclienturl": getVpnProperty("vpn.clienturl")})

        return userData

    def createSshUserData(self, vcInstance):
        table = self.conn.getTable("VCLOUD_KEY_PAIR")
        sshkey = self.conn.selectOne(
            table.select(table.c.KEY_NO == vcInstance["KEY_PAIR_NO"]))
        # UserDataを作成
        userData = {}
        # ZIPパスワード
        userData.update({"sshpubkey": sshkey["KEY_PUBLIC"]})

        return userData

    def makeUserData(self, map):
        if not map or len(map) == 0:
            return None

        userdata = ''
        for key in map.keys():
            value = map[key]
            if isNotEmpty(value):
                if userdata != '':
                    userdata = userdata + ';'

                userdata = userdata + key + "=" + value

        return userdata
class OpenStackInstanceController(object):

    logger = IaasLogger()

    client = None
    conn = None
    platforminfo = None
    
    def __init__(self, platforminfo, openstackiaasclient, conn):
        self.client = openstackiaasclient
        self.conn = conn
        self.platforminfo = platforminfo

        return

    def _createVirtualMachine(self, instanceNo, instanceName, instanceInfo, openstackInstanceInfo):
        # プラットフォーム番号の取得
        platformNo = instanceInfo['PLATFORM_NO']
        # VM作成に必要なパラメータを取得
        # キーペア名
        keyName = openstackInstanceInfo['KEY_NAME']
        if isEmpty(keyName):
            self.logger.debug('      No Keipair specified. Using default.')
            # ファーム番号の取得
            farmNo = instanceInfo['FARM_NO']
            farmTable = self.conn.getTable("FARM")
            farmInfo = self.conn.selectOne(farmTable.select\
                (farmTable.c.FARM_NO==farmNo))
            userNo = farmInfo['USER_NO']
            openstackCertificateTable = self.conn.getTable("OPENSTACK_CERTIFICATE")
            certificateInfo = self.conn.selectOne(openstackCertificateTable.select\
                (and_(openstackCertificateTable.c.USER_NO==userNo, \
                openstackCertificateTable.c.PLATFORM_NO==platformNo)))
            keyName = certificateInfo['DEF_KEYPAIR']
        self.logger.debug('      Keypair: %s' % (keyName))
        # フレーバーID
        instanceType = openstackInstanceInfo['INSTANCE_TYPE']
        self.logger.debug('      Instance Type: %s' % (instanceType))
        # セキュリティグループID
        securityGroup = openstackInstanceInfo['SECURITY_GROUPS']
        self.logger.debug('      Security Group: %s' % (securityGroup))
        # ゾーンID
        availabilityZone = openstackInstanceInfo['AVAILABILITY_ZONE']
        if isEmpty(availabilityZone):
            self.logger.debug('      No Availability Zone specified. Using default.')
            platformOpenStackTable = self.conn.getTable("PLATFORM_OPENSTACK")
            platformOpenStackInfo = self.conn.selectOne(platformOpenStackTable.select\
                (platformOpenStackTable.c.PLATFORM_NO==platformNo))
            availabilityZone = platformOpenStackInfo['AVAILABILITY_ZONE']
        self.logger.debug('      Availability Zone: %s' % (availabilityZone))
        # ネットワークID
        networkId = openstackInstanceInfo['NETWORK_ID']
        if isEmpty(networkId):
            self.logger.debug('      No Network ID specified. Using default.')
            platformOpenStackTable = self.conn.getTable("PLATFORM_OPENSTACK")
            platformOpenStackInfo = self.conn.selectOne(platformOpenStackTable.select\
                (platformOpenStackTable.c.PLATFORM_NO==platformNo))
            networkId = platformOpenStackInfo['NETWORK_ID']
        self.logger.debug('      Network: %s' % (networkId))
        # イメージID
        imageNo = instanceInfo['IMAGE_NO']
        imageOpenstackTable = self.conn.getTable("IMAGE_OPENSTACK")
        imageOpenstackInfo = self.conn.selectOne(imageOpenstackTable.select\
            (imageOpenstackTable.c.IMAGE_NO==imageNo))
        imageId = imageOpenstackInfo['IMAGE_ID']
        self.logger.debug('      Image: %s' % (imageId))
        # ユーザデータ
        userData = self.createUserData(instanceNo, instanceInfo, openstackInstanceInfo)
        userData = self.makeUserData(userData)
        self.logger.debug('      User Data: %s' %(userData))

        try:
            instanceObj = self.client.createVirtualMachine(instanceName, instanceType, \
            imageId, availabilityZone, networkId, userData, securityGroup, keyName)
        except:
            raise IaasException("EPROCESS-001002", [instanceName])

        status = instanceObj.status
        if status != 'ACTIVE':
            raise IaasException("EPROCESS-001003", [instanceName, status])

        openstackInstanceId = instanceObj.id
        connectedNetworks = instanceObj.addresses.keys()
        # IPは1つのみであることを仮定
        connectedNw = connectedNetworks[0]
        try:
            ipAddr = instanceObj.addresses[connectedNw][0]['addr']
            self.logger.debug('      IP Address: %s' %(ipAddr))
        except:
            ipAddr = None

        # データベース更新
        table = self.conn.getTable("OPENSTACK_INSTANCE")
        updateDict = self.conn.selectOne(table.select(table.c.INSTANCE_NO==instanceNo))
        updateDict["STATUS"] = status
        updateDict["INSTANCE_ID"] = openstackInstanceId
        updateDict["PRIVATE_IP_ADDRESS"] = ipAddr
        updateDict["NETWORK_ID"] = networkId
        updateDict["KEY_NAME"] = keyName
        updateDict["AVAILABILITY_ZONE"] = availabilityZone
        sql = table.update(table.c.INSTANCE_NO == updateDict["INSTANCE_NO"], values=updateDict)
        self.conn.execute(sql)
        return True

    def startInstance(self, instanceNo):
        self.logger.info('      StartInstance: %s' % (instanceNo))

        # インスタンスIDの取得
        openstackInstanceTable = self.conn.getTable("OPENSTACK_INSTANCE")
        openstackInstanceInfo = self.conn.selectOne(openstackInstanceTable.select\
            (openstackInstanceTable.c.INSTANCE_NO==instanceNo))
        openstackInstanceId = openstackInstanceInfo['INSTANCE_ID']

        # インスタンス名の取得
        instanceTable = self.conn.getTable("INSTANCE")
        instanceInfo = self.conn.selectOne(instanceTable.select\
            (instanceTable.c.INSTANCE_NO==instanceNo))
        instanceName = instanceInfo['FQDN']

        if isEmpty(openstackInstanceId):
            # 新規作成
            self.logger.info('      Creating Instance: %s' % (instanceName))
            return self._createVirtualMachine(instanceNo, instanceName, instanceInfo, openstackInstanceInfo)
        else:
            # 既存インスタンス
            # ステータスを確認する
            try:
                status = self.client.getVirtualMachineStatus(openstackInstanceId)
            except:
                raise IaasException("EPROCESS-001008", [instanceName])
            if status == 'ACTIVE':
                # 既にインスタンスは起動しているため、statusを更新して終了する。
                self.logger.info('      Instance: %s is already ACTIVE' % (instanceName))
                # データベース更新
                table = self.conn.getTable("OPENSTACK_INSTANCE")
                updateDict = self.conn.selectOne(table.select(table.c.INSTANCE_NO==instanceNo))
                updateDict["STATUS"] = status
                sql = table.update(table.c.INSTANCE_NO == updateDict["INSTANCE_NO"], values=updateDict)
                self.conn.execute(sql)
                return True
            elif status == 'ERROR':
                # インスタンスの状態がERRORならば、起動は意味がないのでエラーにする。
                self.logger.info('      Instance: %s is in ERROR status' % (instanceName))
                raise IaasException("EPROCESS-001003", [instanceName, status])
            else:
                # 既に作成され、停止しているインスタンスを起動する。
                # SHUTOFF 状態のインスタンスに対して起動するのが通常の処理だが、
                # SHUTOFF 状態以外の場合でも、起動を試みて結果を返す。
                self.logger.info('      Starting Instance: %s' % (instanceName))
                try:
                    instanceObj = self.client.startVirtualMachine(openstackInstanceId)
                except:
                    raise IaasException("EPROCESS-001004", [instanceName])
                status = instanceObj.status

                self.logger.info('      StartInstance finished. Status: %s' % (status))
                if status != 'ACTIVE':
                    raise IaasException("EPROCESS-001003", [instanceName, status])
                # データベース更新
                table = self.conn.getTable("OPENSTACK_INSTANCE")
                updateDict = self.conn.selectOne(table.select(table.c.INSTANCE_NO==instanceNo))
                updateDict["STATUS"] = status
                sql = table.update(table.c.INSTANCE_NO == updateDict["INSTANCE_NO"], values=updateDict)
                self.conn.execute(sql)
                return True

    def stopInstance(self, instanceNo):
        self.logger.info('      StopInstance: %s' % (instanceNo))

        # インスタンスIDの取得
        openstackInstanceTable = self.conn.getTable("OPENSTACK_INSTANCE")
        openstackInstanceInfo = self.conn.selectOne(openstackInstanceTable.select\
            (openstackInstanceTable.c.INSTANCE_NO==instanceNo))
        openstackInstanceId = openstackInstanceInfo['INSTANCE_ID']
        # インスタンス名の取得
        instanceTable = self.conn.getTable("INSTANCE")
        instanceInfo = self.conn.selectOne(instanceTable.select\
            (instanceTable.c.INSTANCE_NO==instanceNo))
        instanceName = instanceInfo['FQDN']

        if isEmpty(openstackInstanceId):
            # 一度もStartしたことがない
            self.logger.info('      Nonexistent Instance: %s' % (instanceName))
            raise IaasException("EPROCESS-001006", [instanceName])

        # ステータスを確認する
        try:
            status = self.client.getVirtualMachineStatus(openstackInstanceId)
        except:
            raise IaasException("EPROCESS-001008", [instanceName])
        if status == 'SHUTOFF':
            # 既にインスタンスは起動しているため、statusを更新して終了する。
            self.logger.info('      Instance: %s is already SHUTOFF' % (instanceName))
            # データベース更新
            table = self.conn.getTable("OPENSTACK_INSTANCE")
            updateDict = self.conn.selectOne(table.select(table.c.INSTANCE_NO==instanceNo))
            updateDict["STATUS"] = status
            sql = table.update(table.c.INSTANCE_NO == updateDict["INSTANCE_NO"], values=updateDict)
            self.conn.execute(sql)
            return True

        self.logger.info('      Stopping Instance: %s' % (instanceName))
        try:
            instanceObj = self.client.stopVirtualMachine(openstackInstanceId)
        except:
            raise IaasException("EPROCESS-001006", [instanceName])

        status = instanceObj.status
        if status != 'SHUTOFF':
            raise IaasException("EPROCESS-001007", [instanceName, status])

        self.logger.info('      StopInstance finished. Status: %s' % (status))

        # データベース更新
        table = self.conn.getTable("OPENSTACK_INSTANCE")
        updateDict = self.conn.selectOne(table.select(table.c.INSTANCE_NO==instanceNo))
        updateDict["STATUS"] = status
        sql = table.update(table.c.INSTANCE_NO == updateDict["INSTANCE_NO"], values=updateDict)
        self.conn.execute(sql)

        return True

    def terminateInstance(self, instanceNo):
        self.logger.info('      TerminateInstance: %s' % (instanceNo))

        # インスタンスIDの取得
        openstackInstanceTable = self.conn.getTable("OPENSTACK_INSTANCE")
        openstackInstanceInfo = self.conn.selectOne(openstackInstanceTable.select\
            (openstackInstanceTable.c.INSTANCE_NO==instanceNo))
        openstackInstanceId = openstackInstanceInfo['INSTANCE_ID']
        # インスタンス名の取得
        instanceTable = self.conn.getTable("INSTANCE")
        instanceInfo = self.conn.selectOne(instanceTable.select\
            (instanceTable.c.INSTANCE_NO==instanceNo))
        instanceName = instanceInfo['FQDN']
        if isEmpty(openstackInstanceId):
            # 一度もStartしたことがない
            raise IaasException("EPROCESS-001009", [instanceName])

        # ステータスを確認する
        try:
            status = self.client.getVirtualMachineStatus(openstackInstanceId)
        except:
            raise IaasException("EPROCESS-001008", [instanceName])
        self.logger.info('      Instance: %s, Status: %s' % (instanceName, status))

        if status != 'SHUTOFF':
            # 削除を許さない。
            self.logger.error('      Instance: %s cannot be terminated because the status is not SHUTOFF (%s)' % (instanceName, status))
            raise IaasException("EPROCESS-001010", [instanceName])
        else:
            self.logger.info('      Terminating Instance: %s' % (instanceName))
            try:
                self.client.deleteVirtualMachine(openstackInstanceId)
            except:
                raise IaasException("EPROCESS-001010", [instanceName])
            # ステータスは確認しない
            self.logger.info('      Terminated %s' % (instanceName))

        return True

    def createUserData(self, instanceNo, pccInstance, azureInstance):

        table = self.conn.getTable("FARM")
        farm = self.conn.selectOne(table.select(table.c.FARM_NO==pccInstance["FARM_NO"]))

        #UserDataを作成
        userData = {}
        #DB情報
        userData.update({"instanceName": pccInstance["INSTANCE_NAME"]})
        userData.update({"farmName": farm["FARM_NAME"]})
        # FQDN
        userData.update({"hostname": pccInstance["FQDN"]})
        #初期スクリプト情報
        userData.update({"scriptserver": getScriptProperty("script.server")})

        #DNS情報
        userData.update(self.createDnsUserData(instanceNo))

        # Puppet情報
        userData.update(self.createPuppetUserData())

        # VPN情報
        internal = self.platforminfo["internal"]
        if (internal == 0):
            userData.update(self.createVpnUserData(pccInstance))

        return userData;

    def  createDnsUserData(self,instanceNo):
        # UserDataを作成
        userData = {}
        # Primary DNSサーバ
        userData.update({"dns": getDnsProperty("dns.server")})

        # Secondry DNSサーバ
        dns2 = getDnsProperty("dns.server2")
        if (isNotEmpty(dns2)):
            userData.update({"dns2": dns2})

        # DNSドメイン
        userData.update({"dnsdomain": getDnsProperty("dns.domain")})

        return userData;

    def createPuppetUserData(self):
        # UserDataを作成
        userData = {}
        # PuppetMaster情報
        userData.update({"puppetmaster": getPuppetProperty("puppet.masterHost")})
        return userData;

    def createVpnUserData(self, pccInstance):
        # UserDataを作成
        userData = {}

        #VPN情報のユーザとパスワードをセットする
        userData.update({"vpnuser": pccInstance["FQDN"]})
        userData.update({"vpnuserpass": pccInstance["INSTANCE_CODE"]})

        # VPNサーバ情報
        userData.update({"vpnserver": getVpnProperty("vpn.server")})
        userData.update({"vpnport": getVpnProperty("vpn.port")})
        # userData.update({"vpnuser": getVpnProperty("vpn.user")})
        # userData.update({"vpnuserpass": getVpnProperty("vpn.userpass")})

        # ZIPパスワード
        userData.update({"vpnzippass": getVpnProperty("vpn.zippass")})

        # クライアント証明書ダウンロードURL
        userData.update({"vpnclienturl": getVpnProperty("vpn.clienturl")})
        
        return userData;

    def makeUserData(self, map):
        if not map or len(map) == 0:
            return None

        userdata = ''
        for key in map.keys():
            value = map[key]
            if isNotEmpty(value):
                if userdata != '':
                    userdata = userdata + ';'

                userdata = userdata + key + "=" + value

        return userdata
class azureInstanceController(object):

    logger = IaasLogger()

    client = None
    conn = None
    platforminfo = None
    volumecontroller = None

    def __init__(self, platforminfo, azureiaasclient, conn):
        self.client = azureiaasclient
        self.conn = conn
        self.platforminfo = platforminfo
        self.volumecontroller = azureVolumeController(self.platforminfo, self.client, self.conn)
        self.passwordencryptor = PasswordEncryptor()

    def _generateOsHardDisk(self, storageAccountName, instanceName, imageName):
        # OS用ハードディスクの設定を生成する
        # URLを生成
        mediaLink = 'https://%s.blob.core.windows.net/vhds/%s.vhd' % \
            (storageAccountName, instanceName)
        return self.client.generateOSHardDiskConfig(mediaLink, imageName)

    def _generateConfigurationSet(self, osType, instanceNo):
        # 仮想マシン作成時に指定する設定を生成する
        instanceTable = self.conn.getTable("INSTANCE")
        instanceInfo = self.conn.selectOne(instanceTable.select\
            (instanceTable.c.INSTANCE_NO==instanceNo))
        # ホスト名
        hostName = instanceInfo['INSTANCE_NAME']

        farmNo = instanceInfo['FARM_NO']
        farmTable = self.conn.getTable("FARM")
        farmInfo = self.conn.selectOne(farmTable.select\
            (farmTable.c.FARM_NO==farmNo))
        userNo = farmInfo['USER_NO']
        userTable = self.conn.getTable("USER")
        userInfo = self.conn.selectOne(userTable.select\
            (userTable.c.USER_NO==userNo))

        azureInstanceTable = self.conn.getTable("AZURE_INSTANCE")
        azureInstanceInfo = self.conn.selectOne(azureInstanceTable.select\
            (azureInstanceTable.c.INSTANCE_NO==instanceNo))

        platformNo = instanceInfo['PLATFORM_NO']
        azureCertificateTable = self.conn.getTable("AZURE_CERTIFICATE")
        azureCertificateInfo = self.conn.selectOne(azureCertificateTable.select\
            (azureCertificateTable.c.USER_NO==userNo and azureCertificateTable.c.PLATFORM_NO==platformNo))
        keyPublic = azureCertificateInfo['KEY_PUBLIC']

        # カスタムデータ
        userData = self.createUserData(instanceNo, instanceInfo, azureInstanceInfo, keyPublic)
        userData = self.makeUserData(userData)
        customData = userData
        self.logger.debug("userData:"+userData)

        # Salt情報
        pccSystemInfoTable = self.conn.getTable("PCC_SYSTEM_INFO")
        pccSystemInfo = self.conn.selectOne(pccSystemInfoTable.select())

        # パスワード復号化
        userPassword = self.passwordencryptor.decrypt(userInfo['PASSWORD'], pccSystemInfo['SECRET_KEY'])

        if osType == 'Linux':
            # Linuxのユーザ名 (rootのsshキー認証が設定できるのが望ましい)
            userName = userInfo['USERNAME']

            return self.client.generateLinuxConfig(hostName, userName, userPassword, customData)
        elif osType == 'Windows':
            # Windowsのユーザ名
            userName = userInfo['USERNAME']

            return self.client.generateWindowsConfig(hostName, userName, userPassword, customData)
        else:
            return None

    def _generateVirtualMachineName(self, instanceNo):
        # インスタンスNoとサーバ名を組み合わせてAzureの仮想マシン名を生成する
        instanceTable = self.conn.getTable("INSTANCE")
        instanceInfo = self.conn.selectOne(instanceTable.select\
            (instanceTable.c.INSTANCE_NO==instanceNo))
        # サーバ名
        instanceName = instanceInfo['INSTANCE_NAME']

        # "インスタンスNo"_"サーバ名"をAzureの仮想マシン名とする
        return '%s_%s' % (instanceNo, instanceName)

    def _createInstance(self, platformNo, instanceNo):
        # 作成パラメータの取得
        platformAzureTable = self.conn.getTable("PLATFORM_AZURE")
        platformAzureInfo = self.conn.selectOne(platformAzureTable.select\
            (platformAzureTable.c.PLATFORM_NO==platformNo))

        # クラウドサービス名
        cloudService = platformAzureInfo['CLOUD_SERVICE_NAME']
        self.logger.debug('      Cloud Serivce: %s' % (cloudService))
        # ストレージアカウント名
        storageAccount = platformAzureInfo['STORAGE_ACCOUNT_NAME']
        self.logger.debug('      Storage Account: %s' % (storageAccount))
        # ネットワーク名
        networkName = platformAzureInfo['NETWORK_NAME']
        self.logger.debug('      Network: %s' % (networkName))

        # インスタンス名
        instanceName = self._generateVirtualMachineName(instanceNo)
        self.logger.debug('      Virtual Machine Name: %s' % (instanceName))

        # インスタンスタイプ
        azureInstanceTable = self.conn.getTable("AZURE_INSTANCE")
        azureInstanceInfo = self.conn.selectOne(azureInstanceTable.select\
            (azureInstanceTable.c.INSTANCE_NO==instanceNo))
        instanceType = azureInstanceInfo['INSTANCE_TYPE']
        self.logger.debug('      Instance Type: %s' % (instanceType))

        # 可用性セット
        availabilitySet = azureInstanceInfo['AVAILABILITY_SET']
        self.logger.debug('      Availability Set: %s' % (availabilitySet))

        # サブネットID
        subnetID = azureInstanceInfo['SUBNET_ID']
        self.logger.debug('      Subnet ID: %s' % (subnetID))
        networkConfig = self.client.generateNetworkConfig(subnetID)

        # イメージ名
        instanceTable = self.conn.getTable("INSTANCE")
        instanceInfo = self.conn.selectOne(instanceTable.select\
            (instanceTable.c.INSTANCE_NO==instanceNo))
        imageNo = instanceInfo['IMAGE_NO']
        imageAzureTable = self.conn.getTable("IMAGE_AZURE")
        imageAzureInfo = self.conn.selectOne(imageAzureTable.select\
            (imageAzureTable.c.IMAGE_NO==imageNo))
        imageName = imageAzureInfo['IMAGE_NAME']
        self.logger.debug('      Image: %s' % (imageName))

        # OSタイプ(Azureから取得)
        osType = self.client.identifyImageOsType(imageName)
        self.logger.debug('      OS: %s' % (osType))

        # ホスト名、パスワード等のOSにまつわる設定
        osConfig = self._generateConfigurationSet(osType, instanceNo)
        osHardDisk = self._generateOsHardDisk(storageAccount, instanceName, imageName)

        # VM作成
        status = self.client.createVirtualMachine(cloudService, instanceName, \
            osConfig, osHardDisk, instanceType, networkConfig, networkName, availabilitySet)
        # プライベートIPを取得する前に、VMの作成成功を確認する
        privateIp = self.client.getVirtualMachineIpAddress(cloudService, instanceName)
        self.logger.debug('      Instance: %s, Status: %s, Private IP Address: %s' \
            % (instanceName, status, privateIp))

        # 異常系テストコード
        #status = 'None'
        if status != 'ReadyRole':
            # 新規作成時、VMが起動成功しなかったら、データベースを更新せずに終了
            # status ReadyRoleになる前にタイムアウトした場合と、最終的にReadyRoleにならない場合に分けて検討する必要あり。
            raise IaasException("EPROCESS-000918", [instanceName, status])

        # データベース更新
        table = self.conn.getTable("AZURE_INSTANCE")
        updateDict = self.conn.selectOne(table.select(table.c.INSTANCE_NO==instanceNo))
        updateDict["INSTANCE_NAME"] = instanceName
        updateDict["STATUS"] = status
        updateDict["PRIVATE_IP_ADDRESS"] = privateIp
        sql = table.update(table.c.INSTANCE_NO == updateDict["INSTANCE_NO"], values=updateDict)
        self.conn.execute(sql)

    def startInstance(self, instanceNo):
        self.logger.info('      StartInstance: %s' % (instanceNo))

        # プラットフォーム番号の取得
        instanceTable = self.conn.getTable("INSTANCE")
        instanceInfo = self.conn.selectOne(instanceTable.select\
            (instanceTable.c.INSTANCE_NO==instanceNo))
        platformNo = instanceInfo['PLATFORM_NO']

        # 仮想マシンの起動実績確認
        azureInstanceTable = self.conn.getTable("AZURE_INSTANCE")
        azureInstanceInfo = self.conn.selectOne(azureInstanceTable.select\
            (azureInstanceTable.c.INSTANCE_NO==instanceNo))
        # インスタンス名
        instanceName = azureInstanceInfo['INSTANCE_NAME']
        if isEmpty(instanceName):
            # 仮想マシンの新規作成
            self._createInstance(platformNo, instanceNo)
            return
        else:
            # クラウドサービス名
            platformAzureTable = self.conn.getTable("PLATFORM_AZURE")
            platformAzureInfo = self.conn.selectOne(platformAzureTable.select\
                (platformAzureTable.c.PLATFORM_NO==platformNo))
            cloudService = platformAzureInfo['CLOUD_SERVICE_NAME']

            # 既存仮想マシンの起動
            # Azure上に仮想マシンが存在するか確認
            status = self.client.getVirtualMachineStatus(cloudService, instanceName)
            self.logger.info('      Instance: %s, Status: %s' % (instanceName, status))
            if status is None:
                # インスタンスが存在しないまたは、状態取得に失敗した場合は、処理を終了する
                # ステータスは変更しない
                raise IaasException("EPROCESS-000914", [instanceName])
            elif status == 'ReadyRole':
                self.logger.info('      Instance %s is already running' % (instanceName))
                # インスタンスタイプをチェックし、食い違う場合は警告をログに出力する
                # インスタンスタイプ
                instanceType = azureInstanceInfo['INSTANCE_TYPE']
                currentInstanceType = self.client.getVirtualMachineType(cloudService, instanceName)
                if currentInstanceType != instanceType:
                    raise IaasException("EPROCESS-000913", [instanceName])
                # Azure上では起動している場合、DBを更新して終了。
                pass
            else:
                # ReadyRole以外の場合、起動を試みる
                # インスタンスタイプをチェックし、食い違う場合は警告をログに出力する
                # インスタンスタイプ
                instanceType = azureInstanceInfo['INSTANCE_TYPE']
                currentInstanceType = self.client.getVirtualMachineType(cloudService, instanceName)
                if currentInstanceType != instanceType:
                    self.logger.info('      Changing its instance type to %s' % (instanceType))

                    # サブネット
                    subnetID = azureInstanceInfo['SUBNET_ID']
                    self.logger.info('      Subnet ID: %s' % (subnetID))
                    networkConfig = self.client.generateNetworkConfig(subnetID)
                    # 可用性セット
                    availabilitySet = azureInstanceInfo['AVAILABILITY_SET']
                    self.logger.info('      Availability Set: %s' % (availabilitySet))

                    # インスタンスタイプの変更を反映
                    newInstanceType = self.client.updateVirtualMachineType(cloudService, instanceName, instanceType, \
                                                                           networkConfig, availabilitySet)
                    if isEmpty(newInstanceType):
                        # インスタンスタイプの変更に失敗した場合は、起動も行わない
                        raise IaasException("EPROCESS-000913", [instanceName])
                    self.logger.info('      Instance type for %s has been updated: %s' % (instanceName, newInstanceType))

                # インスタンス起動
                status = self.client.startVirtualMachine(cloudService, instanceName)

            # 異常系テストコード
            #status = 'None'
            if status != 'ReadyRole':
                # VMが起動成功しなかったら、データベースを更新せずに終了
                raise IaasException("EPROCESS-000906", [instanceName, status])

            # データベース更新
            table = self.conn.getTable("AZURE_INSTANCE")
            updateDict = self.conn.selectOne(table.select(table.c.INSTANCE_NO==instanceNo))
            updateDict["STATUS"] = status
            sql = table.update(table.c.INSTANCE_NO == updateDict["INSTANCE_NO"], values=updateDict)
            self.conn.execute(sql)
            return

    def stopInstance(self, instanceNo):
        # インスタンス名の取得
        azureInstanceTable = self.conn.getTable("AZURE_INSTANCE")
        azureInstanceInfo = self.conn.selectOne(azureInstanceTable.select\
            (azureInstanceTable.c.INSTANCE_NO==instanceNo))
        instanceName = azureInstanceInfo['INSTANCE_NAME']

        #1度も起動されていない
        if (isEmpty(instanceName)) :
            return

        instanceTable = self.conn.getTable("INSTANCE")
        instanceInfo = self.conn.selectOne(instanceTable.select\
            (instanceTable.c.INSTANCE_NO==instanceNo))
        platformNo = instanceInfo['PLATFORM_NO']

        platformAzureTable = self.conn.getTable("PLATFORM_AZURE")
        platformAzureInfo = self.conn.selectOne(platformAzureTable.select\
            (platformAzureTable.c.PLATFORM_NO==platformNo))

        # クラウドサービス名の取得
        cloudService = platformAzureInfo['CLOUD_SERVICE_NAME']


        status = self.client.getVirtualMachineStatus(cloudService, instanceName)
        self.logger.info('      Instance: %s, Status: %s' % (instanceName, status))

        if status != 'ReadyRole' and status != 'RoleStateUnknown':
            if status == 'StoppedVM':
                self.logger.info('      Instance: %s is already stopped' % (instanceName))
            else:
                # 停止できる状態ではない。
                raise IaasException("EPROCESS-000908", [instanceName, status])
        else:
            status = self.client.stopVirtualMachine(cloudService, instanceName)

        # データベース更新
        table = self.conn.getTable("AZURE_INSTANCE")
        updateDict = self.conn.selectOne(table.select(table.c.INSTANCE_NO==instanceNo))
        updateDict["STATUS"] = status
        sql = table.update(table.c.INSTANCE_NO == updateDict["INSTANCE_NO"], values=updateDict)
        self.conn.execute(sql)

        # ボリュームに関する処理
        azureDiskTable = self.conn.getTable("AZURE_DISK")
        disks = self.conn.select(azureDiskTable.select(azureDiskTable.c.INSTANCE_NO==instanceNo))

        for azureDisk in disks:
            self.volumecontroller.stopVolume(instanceNo, azureDisk["DISK_NO"])

        return

    def terminateInstance(self, instanceNo):
        instanceTable = self.conn.getTable("INSTANCE")
        instanceInfo = self.conn.selectOne(instanceTable.select\
            (instanceTable.c.INSTANCE_NO==instanceNo))
        platformNo = instanceInfo['PLATFORM_NO']

        platformAzureTable = self.conn.getTable("PLATFORM_AZURE")
        platformAzureInfo = self.conn.selectOne(platformAzureTable.select\
            (platformAzureTable.c.PLATFORM_NO==platformNo))

        # クラウドサービス名の取得
        cloudService = platformAzureInfo['CLOUD_SERVICE_NAME']
        # ストレージアカウント名の取得
        storageAccount = platformAzureInfo['STORAGE_ACCOUNT_NAME']

        # インスタンス名の取得
        azureInstanceTable = self.conn.getTable("AZURE_INSTANCE")
        azureInstanceInfo = self.conn.selectOne(azureInstanceTable.select\
            (azureInstanceTable.c.INSTANCE_NO==instanceNo))
        instanceName = azureInstanceInfo['INSTANCE_NAME']

        status = self.client.getVirtualMachineStatus(cloudService, instanceName)
        self.logger.info('      Instance: %s, Status: %s' % (instanceName, status))

        if status is None:
            # 既に削除されているので、何もしない
            self.logger.info('      Instance: %s does not exist, Status: %s' % (instanceName, status))
            self.conn.info(instanceInfo["FARM_NO"], None, None, instanceNo, \
                           instanceInfo["INSTANCE_NAME"], "AzureInstanceNotExist",["AZURE", instanceName, status])
        elif status == 'StoppedVM':
            self.client.deleteVirtualMachine(cloudService, instanceName, storageAccount, \
                                             instanceNo, instanceInfo["FARM_NO"], instanceInfo["INSTANCE_NAME"])
            self.logger.info('      Terminated %s' % (instanceName))
        else:
            # 削除を許さない。
            self.logger.error('      Instance: %s cannot be terminated because the status is not StoppedVM (%s)' % (instanceName, status))
            self.conn.error(instanceInfo["FARM_NO"], None, None, instanceNo, \
                            instanceInfo["INSTANCE_NAME"], "AzureInstanceDeleteFail",["AZURE", instanceName, status])
            raise IaasException("EPROCESS-000904", [instanceName])

        # データベース更新
        # テスト目的で、terminate後のDB状態でstart(作成)できるようにしている
        table = self.conn.getTable("AZURE_INSTANCE")
        updateDict = self.conn.selectOne(table.select(table.c.INSTANCE_NO==instanceNo))
        updateDict["INSTANCE_NAME"] = None
        updateDict["STATUS"] = None
        updateDict["SUBNET_ID"] = None
        updateDict["PRIVATE_IP_ADDRESS"] = None
        sql = table.update(table.c.INSTANCE_NO == updateDict["INSTANCE_NO"], values=updateDict)
        self.conn.execute(sql)
        return

    def createUserData(self, instanceNo, pccInstance, azureInstance, keyPublic):

        table = self.conn.getTable("FARM")
        farm = self.conn.selectOne(table.select(table.c.FARM_NO==pccInstance["FARM_NO"]))

        #UserDataを作成
        userData = {}
        #DB情報
        userData.update({"instanceName": pccInstance["INSTANCE_NAME"]})
        userData.update({"farmName": farm["FARM_NAME"]})
        # FQDN
        userData.update({"hostname": pccInstance["FQDN"]})
        #初期スクリプト情報
        userData.update({"scriptserver": getScriptProperty("script.server")})
        # Publicキー
        userData.update({"sshpubkey": keyPublic})

        #DNS情報
        userData.update(self.createDnsUserData(instanceNo))

        # Puppet情報
        userData.update(self.createPuppetUserData())

        # VPN情報
        #     VPNについては別途検討とする
        #internal = self.platforminfo["internal"]
        #if (internal == 0):
        #    userData.update(self.createVpnUserData(pccInstance))

        return userData;

    def  createDnsUserData(self,instanceNo):
        # UserDataを作成
        userData = {}
        # Primary DNSサーバ
        userData.update({"dns": getDnsProperty("dns.server")})

        # Secondry DNSサーバ
        dns2 = getDnsProperty("dns.server2")
        if (isNotEmpty(dns2)):
            userData.update({"dns2": dns2})

        # DNSドメイン
        userData.update({"dnsdomain": getDnsProperty("dns.domain")})

        return userData;

    def createPuppetUserData(self):
        # UserDataを作成
        userData = {}
        # PuppetMaster情報
        userData.update({"puppetmaster": getPuppetProperty("puppet.masterHost")})
        return userData;

    def createVpnUserData(self, pccInstance):
        # UserDataを作成
        userData = {}

        #VPN情報のユーザとパスワードをセットする
        userData.update({"vpnuser": pccInstance["FQDN"]})
        userData.update({"vpnuserpass": pccInstance["INSTANCE_CODE"]})

        # VPNサーバ情報
        userData.update({"vpnserver": getVpnProperty("vpn.server")})
        userData.update({"vpnport": getVpnProperty("vpn.port")})
        # userData.update({"vpnuser": getVpnProperty("vpn.user")})
        # userData.update({"vpnuserpass": getVpnProperty("vpn.userpass")})

        # ZIPパスワード
        userData.update({"vpnzippass": getVpnProperty("vpn.zippass")})

        # クライアント証明書ダウンロードURL
        userData.update({"vpnclienturl": getVpnProperty("vpn.clienturl")})
        
        return userData;

    def makeUserData(self, map):
        if not map or len(map) == 0:
            return None

        userdata = ''
        for key in map.keys():
            value = map[key]
            if isNotEmpty(value):
                if userdata != '':
                    userdata = userdata + ';'

                userdata = userdata + key + "=" + value

        return userdata
class CloudStackLoadBalancercontroller(object):

    logger = IaasLogger()
    client = None
    conn = None
    platforminfo = None

    STOPPED = "STOPPED"
    STARTING = "STARTING"
    RUNNING = "RUNNING"
    STOPPING = "STOPPING"
    CONFIGURING = "CONFIGURING"
    WARNING = "WARNING"

    STATUS = {
        STOPPED: STOPPED,
        RUNNING: RUNNING,
        STOPPING: STOPPING,
        CONFIGURING: CONFIGURING,
        WARNING: WARNING,
    }

    def __init__(self, platforminfo, ec2iaasclientLb, conn):
        self.client = ec2iaasclientLb
        self.conn = conn
        self.platforminfo = platforminfo

    def getStatusString(self, key):
        if not key:
            return "STOPPED"

        value = self.STATUS[key]
        if value != None:
            return value
        return "STOPPED"

    def createLoadBalancer(self, loadBalancerNo):
        tableCSLB = self.conn.getTable("CLOUDSTACK_LOAD_BALANCER")
        csLoadBalancer = self.conn.selectOne(
            tableCSLB.select(tableCSLB.c.LOAD_BALANCER_NO == loadBalancerNo))
        tableLB = self.conn.getTable("LOAD_BALANCER")
        loadBalancer = self.conn.selectOne(
            tableLB.select(tableLB.c.LOAD_BALANCER_NO == loadBalancerNo))

        # ロードバランサ作成情報
        loadBalancerName = csLoadBalancer["NAME"]
        #アルゴリズム
        algorithm = csLoadBalancer["ALGORITHM"]
        # ゾーン
        zoneid = csLoadBalancer["ZONEID"]
        # パブリックポート
        port = csLoadBalancer["PUBLICPORT"]
        # プライベートポート
        private_port = csLoadBalancer["PRIVATEPORT"]

        # ロードバランサの作成
        balancer = self.client.createLoadBalancer(loadBalancerName, algorithm,
                                                  port, private_port, zoneid)

        #実行ログ
        self.logger.info(None, "IPROCESS-200621", [
            loadBalancerName,
        ])

        # イベントログ出力
        self.conn.debug(loadBalancer["FARM_NO"], None, None, None, None,
                        "CloudStackLBCreate", ["CLOUDSTACK", loadBalancerName])

        # データベース更新
        updateDict = self.conn.selectOne(
            tableCSLB.select(tableCSLB.c.LOAD_BALANCER_NO == loadBalancerNo))
        updateDict["LOAD_BALANCER_ID"] = balancer.id
        updateDict["PUBLICIP"] = balancer.ip
        updateDict["STATE"] = balancer.state
        updateDict["ADDRESS_ID"] = balancer.ex_public_ip_id
        sql = tableCSLB.update(
            tableCSLB.c.LOAD_BALANCER_NO == updateDict["LOAD_BALANCER_NO"],
            values=updateDict)
        self.conn.execute(sql)

    def deleteLoadBalancer(self, loadBalancerNo):
        tableCSLB = self.conn.getTable("CLOUDSTACK_LOAD_BALANCER")
        csLoadBalancer = self.conn.selectOne(
            tableCSLB.select(tableCSLB.c.LOAD_BALANCER_NO == loadBalancerNo))
        tableLB = self.conn.getTable("LOAD_BALANCER")
        loadBalancer = self.conn.selectOne(
            tableLB.select(tableLB.c.LOAD_BALANCER_NO == loadBalancerNo))

        # ロードバランサ
        loadBalancer = csLoadBalancer["LOAD_BALANCER_ID"]
        try:
            self.client.deleteLoadBalancer(loadBalancer)

            #実行ログ
            self.logger.info(None, "IPROCESS-200622", [
                csLoadBalancer["NAME"],
            ])

            # イベントログ出力
            self.conn.debug(loadBalancer["FARM_NO"], None, None, None, None,
                            "CloudStackLBDelete",
                            ["CLOUDSTACK", csLoadBalancer["NAME"]])

        except Exception:
            self.logger.error(traceback.format_exc())

        # データベース更新
        updateDict = self.conn.selectOne(
            tableCSLB.select(tableCSLB.c.LOAD_BALANCER_NO == loadBalancerNo))
        updateDict["LOAD_BALANCER_ID"] = None
        updateDict["PUBLICIP"] = None
        updateDict["STATE"] = None
        updateDict["ADDRESS_ID"] = None
        sql = tableCSLB.update(
            tableCSLB.c.LOAD_BALANCER_NO == updateDict["LOAD_BALANCER_NO"],
            values=updateDict)
        self.conn.execute(sql)

    def configureInstances(self, loadBalancerNo):
        tableLBINS = self.conn.getTable("LOAD_BALANCER_INSTANCE")
        loadBalancerInstances = self.conn.select(
            tableLBINS.select(tableLBINS.c.LOAD_BALANCER_NO == loadBalancerNo))

        # 振り分け設定するインスタンスがない場合はスキップ
        if not loadBalancerInstances or len(loadBalancerInstances) == 0:
            return

        tableLB = self.conn.getTable("LOAD_BALANCER")
        loadBalancer = self.conn.selectOne(
            tableLB.select(tableLB.c.LOAD_BALANCER_NO == loadBalancerNo))

        # 振り分けを登録・解除するインスタンスを仕分けする
        enabledInstances = []
        disabledInstances = []

        # 振り分けするインスタンス情報を取得
        instanceMap = {}
        for loadBalancerInstance in loadBalancerInstances:
            table = self.conn.getTable("INSTANCE")
            instanceNo = loadBalancerInstance["INSTANCE_NO"]

            #インスタンス獲得
            instance = self.conn.selectOne(
                table.select(table.c.INSTANCE_NO == instanceNo))
            instanceMap.update({instanceNo: instance})

            # ロードバランサが無効の場合は振り分けを解除する
            if not isBit(loadBalancer["ENABLED"]):
                disabledInstances.append(instance)
                continue
            # インスタンスが無効の場合は振り分けを解除する
            if not isBit(instance["ENABLED"]):
                disabledInstances.append(instance)
                continue

            if isBit(loadBalancerInstance["ENABLED"]):
                enabledInstances.append(instance)
            else:
                disabledInstances.append(instance)

        # 振り分けを登録する
        self.registerInstances(loadBalancerNo, loadBalancer["FARM_NO"],
                               enabledInstances, loadBalancerInstances)
        # 振り分けを解除する
        self.unregisterInstances(loadBalancerNo, loadBalancer["FARM_NO"],
                                 disabledInstances, loadBalancerInstances)

    def registerInstances(self, loadBalancerNo, farmNo, instances,
                          loadBalancerInstances):
        if not instances or len(instances) == 0:
            # 振り分け登録するインスタンスがない場合はスキップ
            return

        # 振り分けされていないインスタンス番号を抽出
        tmpInstances = []
        for loadBalancerInstance in loadBalancerInstances:
            for instance in instances:
                if instance["INSTANCE_NO"] == loadBalancerInstance[
                        "INSTANCE_NO"]:
                    status = self.getStatusString(
                        loadBalancerInstance["STATUS"])
                    if status == self.STOPPED:
                        tmpInstances.append(instance)

        instances = tmpInstances
        # 振り分けされていないインスタンスがない場合はスキップ
        if not instances or len(instances) == 0:
            return

        # 起動しているインスタンス番号を抽出
        tmpInstanceNos = []
        for instance in instances:
            status = self.getStatusString(instance["STATUS"])
            if status == self.RUNNING:
                tmpInstanceNos.append(instance)

        instances = tmpInstanceNos

        if not instances or len(instances) == 0:
            # 起動しているインスタンスがない場合はスキップ
            return

        # AWSインスタンスのIDを取得
        instanceIds = []
        tableCSINS = self.conn.getTable("CLOUDSTACK_INSTANCE")
        for instance in instances:
            csInstance = self.conn.selectOne(
                tableCSINS.select(
                    tableCSINS.c.INSTANCE_NO == instance["INSTANCE_NO"]))
            instanceIds.append(csInstance["INSTANCE_ID"])

        try:
            # 振り分け登録
            tableCSLB = self.conn.getTable("CLOUDSTACK_LOAD_BALANCER")
            csLoadBalancer = self.conn.selectOne(
                tableCSLB.select(
                    tableCSLB.c.LOAD_BALANCER_NO == loadBalancerNo))
            loadBalancerid = csLoadBalancer["LOAD_BALANCER_ID"]

            self.client.attach_members(loadBalancerid, instanceIds)

            for instanceid in instanceIds:
                #実行ログ
                self.logger.info(None, "IPROCESS-200623",
                                 [csLoadBalancer["NAME"], instanceid])
                # イベントログ出力
                self.conn.debug(
                    farmNo, None, None, None, None,
                    "CloudStackLBInstancesRegist",
                    ["CLOUDSTACK", csLoadBalancer["NAME"], instanceid])

        except Exception, e:
            self.logger.error(traceback.format_exc())
            # ステータスの更新
            tableLBINS = self.conn.getTable("LOAD_BALANCER_INSTANCE")
            for instance in instances:
                loadBalancerInstance = self.conn.selectOne(
                    tableLBINS.select(
                        and_(
                            tableLBINS.c.LOAD_BALANCER_NO == loadBalancerNo,
                            tableLBINS.c.INSTANCE_NO ==
                            instance["INSTANCE_NO"])))
                loadBalancerInstance["STATUS"] = self.WARNING
                sql = tableLBINS.update(and_(
                    tableLBINS.c.LOAD_BALANCER_NO ==
                    loadBalancerInstance["LOAD_BALANCER_NO"],
                    tableLBINS.c.INSTANCE_NO ==
                    loadBalancerInstance["INSTANCE_NO"]),
                                        values=loadBalancerInstance)
                self.conn.execute(sql)

            raise

        # ステータスの更新
        tableLBINS = self.conn.getTable("LOAD_BALANCER_INSTANCE")
        for instance in instances:
            loadBalancerInstance = self.conn.selectOne(
                tableLBINS.select(
                    and_(tableLBINS.c.LOAD_BALANCER_NO == loadBalancerNo,
                         tableLBINS.c.INSTANCE_NO == instance["INSTANCE_NO"])))
            loadBalancerInstance["STATUS"] = self.RUNNING
            sql = tableLBINS.update(and_(
                tableLBINS.c.LOAD_BALANCER_NO ==
                loadBalancerInstance["LOAD_BALANCER_NO"],
                tableLBINS.c.INSTANCE_NO ==
                loadBalancerInstance["INSTANCE_NO"]),
                                    values=loadBalancerInstance)
            self.conn.execute(sql)
Ejemplo n.º 14
0
#
# You should have received a copy of the GNU General Public License
# along with PrimeCloud Controller(TM). If not, see <http://www.gnu.org/licenses/>.
#

from iaasgw.log.log import IaasLogger
import base64
import hashlib
import hmac
import json
import logging
import sys
import urllib
import urllib2

logger = IaasLogger()


class PccAPIException(Exception):
    """ generic zabbix api exception
        code list:
        -32602 - Invalid params (eg already exists)
        -32500 - no permissions
    """
    pass


class Already_Exists(PccAPIException):
    pass

 # coding: UTF-8
 #
 # Copyright 2014 by SCSK Corporation.
 # 
 # This file is part of PrimeCloud Controller(TM).
 # 
 # PrimeCloud Controller(TM) is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation, either version 2 of the License, or
 # (at your option) any later version.
 # 
 # PrimeCloud Controller(TM) is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 # GNU General Public License for more details.
 # 
 # You should have received a copy of the GNU General Public License
 # along with PrimeCloud Controller(TM). If not, see <http://www.gnu.org/licenses/>.
 # 
from iaasgw.db.mysqlConnector import MysqlConnector
from iaasgw.log.log import IaasLogger
from xmlrpclib import datetime
import time

if __name__ == '__main__':


    logger = IaasLogger()
    logger.debug(u"テスト出力", "IPROCESS-200112", ["TEST",])

    print datetime.datetime.today()
Ejemplo n.º 16
0
class OpenStackController(IaasController):

    logger = IaasLogger()

    conn = None
    accessInfo = None

    client = None
    instancecontroller = None
    volumecontroller = None
    othercontroller = None

    def __init__(self, conn, accessInfo, platforminfo, isLb=False):
        self.conn = conn
        self.accessInfo = accessInfo
        username = accessInfo['OS_ACCESS_ID']
        password = accessInfo['OS_SECRET_KEY']
        self.client = OpenStackIaasClient(platforminfo, username, password)

        #コントローラ作成
        self.instancecontroller = OpenStackInstanceController(
            platforminfo, self.client, self.conn)
        self.volumecontroller = OpenStackVolumeController(
            platforminfo, self.client, self.conn)
        self.othercontroller = OpenStackOtherController(
            platforminfo, self.client, self.conn)

    def __del__(self):
        self.conn.rollback()
        self.conn.close()

    def startInstance(self, instanceNo):
        try:
            self.instancecontroller.startInstance(instanceNo)
        except Exception:
            self.logger.error(traceback.format_exc())
            raise

        # ボリュームに関する処理
        table = self.conn.getTable("OPENSTACK_VOLUME")
        volumes = self.conn.select(
            table.select(table.c.INSTANCE_NO == instanceNo))
        for volume in volumes:
            if isNotEmpty(volume["COMPONENT_NO"]):
                # コンポーネント番号がある場合はスキップ
                continue
            #Volumeスタート
            self.volumecontroller.startVolume(instanceNo, volume["VOLUME_NO"])

        self.conn.commit()
        return True

    def stopInstance(self, instanceNo):
        try:
            self.instancecontroller.stopInstance(instanceNo)
        except Exception:
            self.logger.error(traceback.format_exc())
            raise

        try:
            # ボリュームに関する処理
            tableOSVOL = self.conn.getTable("OPENSTACK_VOLUME")
            volumes = self.conn.select(
                tableOSVOL.select(tableOSVOL.c.INSTANCE_NO == instanceNo))

            for volume in volumes:
                self.volumecontroller.stopVolume(instanceNo,
                                                 volume["VOLUME_NO"])

        except Exception:
            self.logger.error(traceback.format_exc())

        self.conn.commit()
        return True

    def terminateInstance(self, instanceNo):
        try:
            self.instancecontroller.terminateInstance(instanceNo)
        except Exception:
            self.logger.error(traceback.format_exc())
            raise

        self.conn.commit()
        return True

    def startVolume(self, instanceNo, volumeNo):
        try:
            self.volumecontroller.startVolume(instanceNo, volumeNo)
        except Exception:
            self.logger.error(traceback.format_exc())
            raise

        self.conn.commit()
        return True

    def stopVolume(self, instanceNo, volumeNo):
        try:
            self.volumecontroller.stopVolume(instanceNo, volumeNo)
        except Exception:
            self.logger.error(traceback.format_exc())
            raise

        self.conn.commit()
        return True

    def deleteVolume(self, volumeId):
        try:
            self.volumecontroller.deleteVolume(volumeId)
        except Exception:
            self.logger.error(traceback.format_exc())
            raise

        self.conn.commit()
        return True

    def describeSecurityGroups(self, vpcid=None):
        securityGroupList = self.client.describeSecurityGroups()
        rtString = ''
        for securityGroup in securityGroupList:
            if rtString != '':
                rtString = rtString + "##"
            rtString = rtString + securityGroup.name + "#" + securityGroup.id

        return "RESULT:" + rtString

    def describeAvailabilityZones(self):
        zoneList = self.client.describeAvailabilityZones()
        rtString = ''
        for zone in zoneList:
            if rtString != '':
                rtString = rtString + "##"
            #必要な情報のみ返却。IDに相当するパラメータがないためNONEをセット
            rtString = rtString + zone.zoneName + "#NONE"

        return "RESULT:" + rtString

    def describeNetwork(self):
        networkList = self.client.describeNetworks()
        rtString = ''
        for nw in networkList:
            if rtString != '':
                rtString = rtString + "##"
            rtString = rtString + nw.id + "#" + nw.label

        return "RESULT:" + rtString

    def describeFlavors(self, flavorIds):
        flavorIdList = flavorIds.split(',')
        flavorNameList = []
        flvs = self.client.describeFlavors()
        rtString = ''
        for flavorId in flavorIdList:
            for flv in flvs:
                if flv.id != flavorId:
                    continue
                if rtString != '':
                    rtString = rtString + "##"
                rtString = rtString + flv.id + "#" + flv.name
                break
            else:
                pass

        return "RESULT:" + rtString

    def describeKeyPairs(self):
        keypairs = self.client.describeKeyPairs()
        rtString = ''
        for keypair in keypairs:
            if rtString != '':
                rtString = rtString + "##"

            #とりあえず必要な情報のみ返します
            rtString = rtString + keypair.name

        self.conn.commit()
        return "RESULT:" + rtString

    def importKeyPair(self, keyName, publicKeyMaterial):
        self.client.createKeyPair(keyName, publicKeyMaterial)
        self.conn.commit()
        return "RESULT:" + ''
Ejemplo n.º 17
0
class CloudStackVolumController(object):
    logger = IaasLogger()
    client = None
    conn = None
    platforminfo = None

    def __init__(self, platforminfo, cs2iaasclient, conn):
        self.client = cs2iaasclient
        self.conn = conn
        self.platforminfo = platforminfo



    def startVolumes(self, instanceNo) :
        # ボリューム情報の取得
        table = self.conn.getTable("CLOUDSTACK_VOLUME")
        volumes = self.conn.select(table.select(table.c.INSTANCE_NO==instanceNo))

        for volume in volumes :
            self.startVolume(instanceNo, volume["VOLUME_NO"])


    def startVolume(self, instanceNo, volumeNo) :
        table = self.conn.getTable("CLOUDSTACK_VOLUME")
        volume = self.conn.selectOne(table.select(table.c.VOLUME_NO==volumeNo))

        # インスタンスIDがある場合はスキップ
        if (isNotEmpty(volume["INSTANCE_ID"])) :
            return

        if (isEmpty(volume["VOLUME_ID"])) :
            # ボリュームIDがない場合は新規作成
            self.createVolume(instanceNo, volumeNo)

        # ボリュームのアタッチ
        self.attachVolume(instanceNo, volumeNo)
        #ディスク認識の為リブート
        ##self.rebootInstance(instanceNo)
        #起動スクリプトを待つ
        time.sleep(10)


    def stopVolumes(self, instanceNo) :
        # ボリューム情報の取得
        csVolumes = self.geCsVolumes(instanceNo)

        for volume in csVolumes :
            self.stopVolume(instanceNo, volume["VOLUME_NO"])


    def stopVolume(self, instanceNo, volumeNo):
        tableCSVOL = self.conn.getTable("CLOUDSTACK_VOLUME")
        csVolumes = self.conn.selectOne(tableCSVOL.select(tableCSVOL.c.VOLUME_NO==volumeNo))

        # ボリュームIDがない場合はスキップ
        if (isEmpty(csVolumes["VOLUME_ID"])):
            return

        # インスタンスIDがない場合はスキップ
        if (isEmpty(csVolumes["INSTANCE_ID"])) :
            return;

        try :
            # ボリュームのデタッチ
            self.detachVolume(instanceNo, volumeNo)

        except Exception, e:
            self.logger.error(traceback.format_exc())
            # 情報が不整合(インスタンス異常終了時など)の場合、警告ログと後始末のみ行う
            self.logger.warn(e.massage);

            updateDict = self.conn.selectOne(tableCSVOL.select(tableCSVOL.c.VOLUME_NO==volumeNo))
            updateDict["STATE"] = "error"
            updateDict["INSTANCE_ID"] = None
            sql = tableCSVOL.update(tableCSVOL.c.VOLUME_NO ==updateDict["VOLUME_NO"], values=updateDict)
            self.conn.execute(sql)
class EC2IaasClient(EC2APNENodeDriver):

    logger = IaasLogger()

    connectionCls = EC2APNEConnection
    type = Provider.EC2
    api_name = 'ec2_ap_northeast'
    name = 'Amazon EC2 (ap-northeast-1)'
    friendly_name = 'Amazon Asia-Pacific Tokyo'
    country = 'JP'
    region_name = 'ap-northeast-1'
    path = '/'

    platformNo = None

    debugout = True

    ############################################################
    #
    #    基礎データ
    #
    ############################################################
    def getPlatformNo(self):
        return self.platformNo

    def setPlatformNo(self, platformNo):
        self.platformNo = platformNo

    ############################################################
    #
    #    参照系  describe
    #
    ############################################################

    def describeImages(self, location=None):
        return None

    def describeImage(self, imageId):
        return NodeImage("IMAGEID",
                         "IMAGELOCATION",
                         "DRIVER",
                         extra={
                             'ROOTDEVICETYPE': "ROOTDEVICETYPE",
                             'PLATFORM': "PLATFORM"
                         })

    #list_nodesとして提供されているが、機能としてはインスタンス指定を利用がいいか?
    def describeInstances(self, instanceid):
        return None

    #list_nodesとして提供されているものをそのまま使って必要な物だけ
    def describeInstance(self, instanceid):
        extra = {}
        extra.update({"availability": "ap-northeast-1"})
        extra.update({"dns_name": "TESTDNS"})
        extra.update({"private_dns": "TEST_PDNS"})
        extra.update({"private_dns": "TEST_PDNS"})
        return TestModule("TEST2", "running", '0.0.0.1', '0.0.0.1', extra)
        #return TestModule("TEST2", "stopped", '0.0.0.1','0.0.0.1', extra)

    #LibCloudで提供されていない為独自実装
    def describeVolume(self, volumeId):
        volumes = self.describeVolumes(volumeId)

        if not volumes or len(volumes) == 0:
            #インスタンスが存在しない場合
            raise IaasException("EPROCESS-000110", [
                volumeId,
            ])

        if len(volumes) > 1:
            #インスタンスを複数参照できた場合
            raise IaasException("EPROCESS-000111", [
                volumeId,
            ])

        return volumes[0]

    #LibCloudで提供されていない為独自実装
    def describeVolumes(self, volumeId):
        #volume = Volume("TESTVOLID", None, None, None, 'in-use', None, None, None)
        volume = Volume("TESTVOLID", None, None, None, 'available', None, None,
                        None)
        volumes = [
            volume,
        ]
        return volumes

    def describeAddress(self, publicIp):
        address = self.describeAddresses(publicIp)

        if not address or len(address) == 0:
            #アドレスが存在しない場合
            raise IaasException("EPROCESS-000117", [
                publicIp,
            ])

        if len(address) > 1:
            #アドレスを複数参照できた場合
            raise IaasException("EPROCESS-000118", [
                publicIp,
            ])

        return address[0]

    #LibCloudで提供されているDescribeAddressesラップ関数は利用形態がマッチしないので独自実装とする
    #本来はpublicIpを省略する事も可能だが用途的に固定する
    def describeAddresses(self, publicIp=None):
        volume = Address(None, None, None)
        volumes = [
            volume,
        ]
        return volumes

    #LibCloudで提供されているdescribeKeyPairsラップ関数はNameの入力が必須である為用途が異なる為、独自実装
    def describeKeyPairs(self):
        return None

    #LibCloudで提供されていない為独自実装
    def describeSecurityGroups(self):
        return None

    #ex_list_availability_zonesとして提供されているものをラップ
    def describeAvailabilityZones(self, only_available=True):
        zone = ExEC2AvailabilityZone("TESTTESTLB", None, None)
        zones = [
            zone,
        ]
        return zones

    #LibCloudで提供されていない為独自実装
    def describeSnapshot(self, snapshotId):
        return None

    #LibCloudで提供されていない為独自実装
    def describeSnapshots(self, snapshotId=None):
        return None

    def describeRegions(self, regionName=None):
        return None

    def describeVpcs(self, vpcId=None):
        return None

    def describeSubnets(self, subnetId=None):
        return None

    def describeTags(self, instanceId=None):
        return None

    ############################################################
    #
    #    Instance 系
    #
    ############################################################

    #*********************そのまま*****************
    def runInstances(self, **kwargs):

        print ">>>>>>>", kwargs

        params = {
            'Action': 'RunInstances',
            'ImageId': kwargs.get('imageId'),
            'InstanceType': kwargs.get('instanceType'),
            'MinCount': kwargs.get('ex_mincount', '1'),
            'MaxCount': kwargs.get('ex_maxcount', '1'),
        }

        if 'securityGroup' in kwargs:
            if not isinstance(kwargs['securityGroup'], list):
                kwargs['securityGroup'] = [kwargs['securityGroup']]
            for sig in range(len(kwargs['securityGroup'])):
                params['SecurityGroup.%d' %
                       (sig + 1, )] = kwargs['securityGroup'][sig]

        if 'blockDeviceMapping' in kwargs:
            if kwargs['blockDeviceMapping']:
                if not isinstance(kwargs['blockDeviceMapping'], list):
                    kwargs['blockDeviceMapping'] = [
                        kwargs['blockDeviceMapping']
                    ]
                for sig, blockDevice in enumerate(
                        kwargs['blockDeviceMapping']):
                    params['BlockDeviceMapping.%d.DeviceName' %
                           (sig + 1, )] = blockDevice["DeviceName"]
                    params['BlockDeviceMapping.%d.VirtualName' %
                           (sig + 1, )] = blockDevice["VirtualName "]

        if 'location' in kwargs:
            availability_zone = kwargs['location']
            if availability_zone:
                if availability_zone != self.region_name:
                    raise IaasException('Invalid availability zone: %s' %
                                        availability_zone)
                params['Placement.AvailabilityZone'] = availability_zone

        if 'kernelId' in kwargs:
            params['KernelId'] = kwargs['kernelId']

        if 'ramdiskId' in kwargs:
            params['RamdiskId'] = kwargs['ramdiskId']

        if 'keyName' in kwargs:
            params['KeyName'] = kwargs['keyName']

        if 'subnetId' in kwargs:
            params['SubnetId'] = kwargs['subnetId']

        if 'userData' in kwargs:
            params['UserData'] = base64.b64encode(kwargs['userData'])

        if 'ex_clienttoken' in kwargs:
            params['ClientToken'] = kwargs['ex_clienttoken']

        extra = {}
        extra.update({"availability": "TESTZONE"})
        extra.update({"'dns_name'": "TESTDNS"})
        extra.update({"'private_dns'": "TEST_PDNS"})
        extra.update({"'private_dns'": "TEST_PDNS"})
        return TestModule("TEST2", "TESTING", '0.0.0.1', '0.0.0.1', extra)

    #LibCloudで提供されていない為独自実装
    def startInstance(self, instanceid):
        params = {'Action': 'StartInstances', 'InstanceId.0': instanceid}
        return {"code": 'code', "name": 'running'}

    #LibCloudで提供されていない為独自実装
    def stopInstance(self, instanceid):
        params = {'Action': 'StopInstances', 'InstanceId.0': instanceid}
        return {"code": 'code', "name": 'stopped'}

    #本来destroy_nodeはnode自体を受け取るがこの関数はIDを受ける形とした
    def terminateInstance(self, instanceid):
        params = {'Action': 'TerminateInstances', 'InstanceId': instanceid}
        return {"code": 'code', "name": 'terminated'}

    ############################################################
    #
    #    Volume 系
    #
    ############################################################

    #LibCloudで提供されていない為独自実装
    def createVolume(self, availabilityZone, size=None, snapshotId=None):
        params = {
            'Action': 'CreateVolume',
            'AvailabilityZone': availabilityZone
        }

        #任意
        if size != None:
            params.update({'Size': size})
        if snapshotId != None:
            params.update({'SnapshotId': snapshotId})

        return Volume("TESTVOLID", None, None, None, 'available', None, None,
                      None)

    #LibCloudで提供されていない為独自実装
    def attachVolume(self, volumeId, instanceId, device):
        params = {
            'Action': 'AttachVolume',
            'VolumeId': volumeId,
            'InstanceId': instanceId,
            'Device': device
        }

        return None

    #LibCloudで提供されていない為独自実装
    def detachVolume(self, volumeId, instanceId=None, device=None):
        params = {'Action': 'DetachVolume', 'VolumeId': volumeId}

        #任意パラメータ
        if instanceId != None:
            params.update({'InstanceId': instanceId})
        if device != None:
            params.update({'Device': device})

        return None

    #LibCloudで提供されていない為独自実装
    def deleteVolume(self, volumeId):
        params = {'Action': 'DeleteVolume', 'VolumeId': volumeId}

    ############################################################
    #
    #    Address 系
    #
    ############################################################

    #LibCloudで提供されていない為独自実装
    #Domainを指定することも可能だが無視する
    def allocateAddress(self):
        params = {'Action': 'AllocateAddress'}

        return None

    #LibCloudで提供されていない為独自実装
    def associateAddress(self, publicIp, instanceId):
        params = {
            'Action': 'AssociateAddress',
            'PublicIp': publicIp,
            'InstanceId': instanceId
        }

    #LibCloudで提供されていない為独自実装
    def disassociateAddress(self, publicIp, instanceId):
        params = {'Action': 'DisassociateAddress', 'PublicIp': publicIp}

    #LibCloudで提供されていない為独自実装
    def releaseAddress(self, publicIp):
        params = {'Action': 'ReleaseAddress', 'PublicIp': publicIp}

    ############################################################
    #
    #    KeyPair 系
    #
    ############################################################

    #LibCloudで提供されてるex_create_keypairはKeyNameを戻り値に含まない為、独自実装
    def createKeyPair(self, keyName):
        params = {'Action': 'CreateKeyPair', 'KeyName': keyName}

    #LibCloudで提供されていない為独自実装
    def deleteKeyPair(self, keyName):
        params = {'Action': 'DeleteKeyPair', 'KeyName': keyName}

    #LibCloudで提供されてるex_import_keypairはファイルベースの為、独自実装
    def importKeyPair(self, keyName, publicKeyMaterial):
        ###########################################
        #
        # まだ動きません   createKeyPairから直接使うとだめ
        # PCCで利用されていない為後回しとする
        #
        ###########################################

        publicKeyMaterial = base64.b64encode(publicKeyMaterial)
        params = {
            'Action': 'ImportKeyPair',
            'KeyName': keyName,
            'PublicKeyMaterial': publicKeyMaterial
        }

    ############################################################
    #
    #    Snapshot 系
    #
    ############################################################

    def createSnapshot(self, volumeId, description=None):
        #Owner, RestorableBy, Filter(name/Value)で絞る事ができるが制限する
        params = {'Action': 'CreateSnapshot', 'VolumeId': volumeId}
        #任意パラメータ
        if description != None:
            params.update({'Description': description})

        return None

    def deleteSnapshot(self, snapshotId):
        params = {'Action': 'DeleteSnapshot', 'SnapshotId': snapshotId}

    ############################################################
    #
    #    Tags 系
    #
    ############################################################

    def createTags(self, instanceId, tagSets):
        if not tagSets:
            return

        params = {'Action': 'CreateTags', 'ResourceId.0': instanceId}
        i = 0
        for tag in tagSets:
            params['Tag.%d.Key' % i] = tag.key
            params['Tag.%d.Value' % i] = tag.value
            i = i + 1
            # ログ出力
            self.logger.info(None, "IPROCESS-100154",
                             [instanceId, tag.key, tag.value])

    def createTag(self, instanceId, tag):
        if not tag:
            return
        tags = [tag]
        self.createTags(instanceId, tags)

    def deleteTags(self, instanceId, tagSets):
        if not tagSets:
            return

        params = {'Action': 'DeleteTags', 'ResourceId.0': instanceId}
        i = 0
        for tag in tagSets:
            params['Tag.%d.Key' % i] = tag.key
            params['Tag.%d.Value' % i] = tag.value
            i = i + 1

    ############################################################
    #
    #    その他
    #
    ############################################################
    def getPasswordData(self, InstanceId):
        params = {'Action': 'GetPasswordData', 'InstanceId': InstanceId}

        elem = self.connection.request(self.path, params=params).object
Ejemplo n.º 19
0
class CloudStackIaasClient(CloudStackNodeDriver):

    logger = IaasLogger()
    platformNo = None
    timeout = 600
    devicetype = None
    username = None
    hostid = None

    connectionCls = PCCCloudStackConnection

    def __init__(self, platforminfo, username, key, secret=None):
        self.platformNo = platforminfo["platformNo"]
        self.username = username
        self.logger.info(u"利用プラットフォーム" + str(self.platformNo))

        #接続情報
        cloudstackInfo = getCloudStackInfo(self.platformNo)
        host = cloudstackInfo["host"]
        path = cloudstackInfo["path"]
        port = cloudstackInfo["port"]
        secure = cloudstackInfo["secure"]
        pltfmNotimeout = cloudstackInfo["timeout"]
        self.devicetype = cloudstackInfo["device"]
        self.hostid = cloudstackInfo["hostid"]

        #タイムアウト
        if pltfmNotimeout is not None:
            self.connectionCls.timeout = int(pltfmNotimeout)

        #プロキシ利用
        useProxy = platforminfo["proxy"]
        if useProxy == 1:
            useProxy = True
        else:
            useProxy = False
        self.connectionCls.useProxy = useProxy

        #プロトコル
        if secure == 1:
            secure = True
        else:
            secure = False

        self.logger.info(u"接続情報==> " + host + ":" + port + path + " secure=" +
                         str(secure))

        CloudStackNodeDriver.__init__(self,
                                      key=key,
                                      secret=secret,
                                      secure=secure,
                                      host=host,
                                      path=path,
                                      port=port)

    ############################################################
    #
    #    基礎データ
    #
    ############################################################
    def getPlatformNo(self):
        return self.platformNo

    def getDeviceType(self):
        return self.devicetype

    def getUsername(self):
        return self.username

    ############################################################
    #
    #    参照系  describe
    #
    ############################################################
    def getHypervisor(self, zoneid):
        args = {'zoneid': zoneid}
        result = self._sync_request('listHypervisors', **args)
        hypervisor = result.get('hypervisor', [])
        return hypervisor[0]

    def describeImages(self, location=None):
        args = {'templatefilter': 'executable'}

        if location is not None:
            args['zoneid'] = location.id

        result = self._sync_request('listTemplates', **args)
        imgs = result.get('template', [])
        return imgs

    def describeImage(self, imageId):
        images = self.describeImages()
        retImage = None
        for image in images:
            if imageId == image['id']:
                retImage = image

        if not retImage:
            #イメージが存在しない場合
            raise IaasException("EPROCESS-000724", [
                imageId,
            ])

        return retImage

    def describeOnlyInstances(self):
        vms = self._sync_request('listVirtualMachines')
        return vms

    def describeInstances(self, instanceid=None, name=None):
        args = {}
        if instanceid is not None:
            args['id'] = instanceid
        if name is not None:
            args['name'] = name

        vms = self._sync_request('listVirtualMachines', **args)
        addrs = self._sync_request('listPublicIpAddresses')

        public_ips = {}
        for addr in addrs.get('publicipaddress', []):
            if 'virtualmachineid' not in addr:
                continue
            vm_id = addr['virtualmachineid']
            if vm_id not in public_ips:
                public_ips[vm_id] = {}
            public_ips[vm_id][addr['ipaddress']] = addr['id']

        nodes = []

        for vm in vms.get('virtualmachine', []):
            private_ips = []

            for nic in vm['nic']:
                if 'ipaddress' in nic:
                    private_ips.append(nic['ipaddress'])

            node = CloudStackNode(
                id=vm['id'],
                name=vm.get('displayname', None),
                state=self.NODE_STATE_MAP[vm['state']],
                #Libcloudのバージョンによってはこちらを利用してください
                #public_ip=public_ips.get(vm['id'], {}).keys(),
                #private_ip=private_ips,
                public_ips=public_ips.get(vm['id'], {}).keys(),
                private_ips=private_ips,
                driver=self,
                extra={
                    'zoneid': vm['zoneid'],
                    'serviceofferingid': vm['serviceofferingid'],
                    'displayname': vm['displayname'],
                })

            addrs = public_ips.get(vm['id'], {}).items()
            addrs = [CloudStackAddress(node, v, k) for k, v in addrs]
            node.extra['ip_addresses'] = addrs

            nodes.append(node)

        return nodes

    def describeInstance(self, instanceid):
        nodes = self.describeInstances(instanceid=instanceid)

        if not nodes or len(nodes) == 0:
            #インスタンスが存在しない場合
            raise IaasException("EPROCESS-000701", [
                instanceid,
            ])

        if len(nodes) > 1:
            #インスタンスを複数参照できた場合
            raise IaasException("EPROCESS-000702", [
                instanceid,
            ])

        return nodes[0]

    def describeVolume(self, volumeId):
        volumes = self.describeVolumes(volumeId=volumeId)

        if not volumes or len(volumes) == 0:
            #インスタンスが存在しない場合
            raise IaasException("EPROCESS-000705", [
                volumeId,
            ])

        if len(volumes) > 1:
            #インスタンスを複数参照できた場合
            raise IaasException("EPROCESS-000706", [
                volumeId,
            ])

        return volumes[0]

    def describeVolumes(self, volumeId=None):
        args = {}
        if volumeId is not None:
            args['id'] = volumeId

        result = self._sync_request('listVolumes', **args)
        volumes = result.get('volume', [])
        return volumes

    def describeKeyPairs(self):
        result = self._sync_request('listSSHKeyPairs')
        keypairs = result.get('sshkeypair', [])
        return keypairs

    def describeSecurityGroups(self):
        result = self._sync_request('listSecurityGroups')
        securityGroups = result.get('securitygroup', [])
        return securityGroups

    def describeAvailabilityZones(self):
        result = self._sync_request('listZones')
        zones = result['zone']
        return zones

    def describeSnapshot(self, snapshotId):
        snapshots = self.describeSnapshots(snapshotId)

        if not snapshots or len(snapshots) == 0:
            #アドレスが存在しない場合
            raise IaasException("EPROCESS-000713", [
                snapshotId,
            ])

        if len(snapshots) > 1:
            #アドレスを複数参照できた場合
            raise IaasException("EPROCESS-000714", [
                snapshotId,
            ])

        return snapshots[0]

    def describeSnapshots(self, snapshotId=None):
        args = {}
        if snapshotId is not None:
            args['id'] = snapshotId

        result = self._sync_request('listSnapshots', **args)

        snapshots = result.get('snapshot', [])

        return snapshots

    def describeLoadBalancer(self, loadBalancerid):
        loadBalancers = self.describeLoadBalancers(loadBalancerid)

        if len(loadBalancers) == 0:
            #インスタンスが存在しない場合
            raise IaasException("EPROCESS-000719", [
                loadBalancerid,
            ])

        if len(loadBalancers) > 1:
            #インスタンスを複数参照できた場合
            raise IaasException("EPROCESS-000720", [
                loadBalancerid,
            ])

        return loadBalancers[0]

    def describeLoadBalancers(self, loadBalancerid=None):
        args = {}
        if loadBalancerid is not None:
            args['id'] = loadBalancerid

        loadBalancers = self._sync_request('listLoadBalancerRules', **args)
        balancers = loadBalancers.get('loadbalancerrule', [])
        return [self._to_balancer(balancer) for balancer in balancers]

    def describeLoadBalancerRuleInstances(self,
                                          loadBalancerid,
                                          instances=None):
        balancer = self.describeLoadBalancer(loadBalancerid)
        members = self._sync_request('listLoadBalancerRuleInstances',
                                     id=balancer.id)
        members = members['loadbalancerruleinstance']
        return [self._to_member(m, balancer.ex_private_port) for m in members]

    def describeServiceOfferings(self, domainid=None):
        args = {}
        if domainid is not None:
            args['domainid'] = domainid

        result = self._sync_request('listServiceOfferings', **args)
        serviceOffs = result['serviceoffering']
        return serviceOffs

    def describeDiskOfferings(self, domainid=None):
        args = {}
        if domainid is not None:
            args['domainid'] = domainid

        result = self._sync_request('listDiskOfferings', **args)
        diskofferings = result['diskoffering']
        return diskofferings

    def describeNetworks(self):
        result = self._sync_request('listNetworks')
        network = result['network']
        return network

    def describePublicIpAddress(self, addressid):
        addresses = self.describePublicIpAddresses(addressid)

        if len(addresses) == 0:
            #インスタンスが存在しない場合
            raise IaasException("EPROCESS-000708", [
                addressid,
            ])

        if len(addresses) > 1:
            #インスタンスを複数参照できた場合
            raise IaasException("EPROCESS-000709", [
                addressid,
            ])

        return addresses[0]

    def describePublicIpAddresses(self, addressid=None):
        args = {}
        if addressid is not None:
            args['id'] = addressid
        result = self._sync_request('listPublicIpAddresses', **args)
        network = result['publicipaddress']
        return network

    ############################################################
    #
    #    Instance 系
    #
    ############################################################
    def runInstances(self, name, dname, serviceofferingid, imageid, zoneid,
                     **kwargs):
        extra_args = {}
        if zoneid is None:
            location = self.describeAvailabilityZones()[0]
            zoneid = location['id']

        #以下任意パラメータ
        if self.hostid is not None:
            extra_args['hostid'] = self.hostid

        network_id = kwargs.pop('network_id', None)
        if network_id is not None:
            extra_args['networkids'] = network_id

        securityGroups = kwargs.pop('securitygroupids', None)
        if securityGroups is not None:
            extra_args['securitygroupnames'] = securityGroups

        keypair = kwargs.pop('keypair', None)
        if keypair is not None:
            extra_args['keypair'] = keypair

        userdata = kwargs.pop('userdata', None)
        if userdata is not None:
            extra_args['userdata'] = base64.b64encode(userdata)

        #インスタンス作成
        result = self._async_request('deployVirtualMachine',
                                     name=name,
                                     displayname=dname,
                                     serviceofferingid=serviceofferingid,
                                     templateid=imageid,
                                     zoneid=zoneid,
                                     **extra_args)

        node = None
        if 'virtualmachine' in result:
            node = result['virtualmachine']
        else:
            raise IaasException("EPROCESS-000703", [])

        return node

    def startInstance(self, instanceid):
        params = {
            'id': instanceid,
        }
        result = self._async_request('startVirtualMachine', **params)

        node = None
        if 'virtualmachine' in result:
            node = result['virtualmachine']
        else:
            raise IaasException("EPROCESS-000715", [])

        return node

    def changeInstance(self, instanceid, serviceofferingid):
        params = {'id': instanceid, 'serviceofferingid': serviceofferingid}
        result = self._sync_request('changeServiceForVirtualMachine', **params)

        node = None
        if 'virtualmachine' in result:
            node = result['virtualmachine']
        else:
            raise IaasException("EPROCESS-000715", [])

        return node

    def stopInstance(self, instanceid):
        params = {'id': instanceid}
        result = self._async_request('stopVirtualMachine', **params)

        node = None
        if 'virtualmachine' in result:
            node = result['virtualmachine']
        else:
            raise IaasException("EPROCESS-000717", [])
        return node

    #本来destroy_nodeはnode自体を受け取るがこの関数はIDを受ける形とした
    def terminateInstance(self, instanceid):
        result = self._async_request('destroyVirtualMachine', id=instanceid)

        node = None
        if 'virtualmachine' in result:
            node = result['virtualmachine']
        else:
            raise IaasException("EPROCESS-000704", [])

        return node

    def rebootInstance(self, instanceid):
        params = {'id': instanceid}
        result = self._async_request('rebootVirtualMachine', **params)

        node = None
        if 'virtualmachine' in result:
            node = result['virtualmachine']
        else:
            raise IaasException("EPROCESS-000717", [])
        return node

    ############################################################
    #
    #    Volume 系
    #
    ############################################################
    def createVolume(self,
                     name,
                     location=None,
                     size=None,
                     snapshotId=None,
                     diskid=None,
                     iscustomized=True):
        args = {}

        if snapshotId is None and diskid is None:
            # ボリューム作成失敗時
            raise IaasException("**********")

        if snapshotId is not None:
            args['snapshotid'] = snapshotId

        if diskid is not None:
            args['diskofferingid'] = diskid

        if size is not None and iscustomized:
            args['size'] = str(size)

        if location is None:
            location = self.describeAvailabilityZones()[0]["id"]
        args['zoneid'] = location

        result = self._async_request('createVolume', name=name, **args)

        volume = None
        if 'volume' in result:
            volume = result['volume']
        else:
            raise IaasException("EPROCESS-000707", [])
        return volume

    def attachVolume(self, volumeId, instanceId, deviceid=None):
        args = {}
        if deviceid is not None:
            args['deviceid'] = deviceid

        result = self._async_request('attachVolume',
                                     id=volumeId,
                                     virtualmachineid=instanceId,
                                     **args)

        volume = result['volume']
        return volume

    def detachVolume(self, volumeId, instanceId=None, deviceid=None):
        args = {}

        if volumeId is not None:
            args['id'] = volumeId
        else:
            if deviceid is not None:
                args['deviceid'] = deviceid
            if instanceId is not None:
                args['virtualmachineid'] = instanceId

        result = self._async_request('detachVolume', **args)

        volume = result['volume']
        return volume

    def deleteVolume(self, volumeId):
        result = self._sync_request('deleteVolume', id=volumeId)

        if result.get('success', '').lower() != 'true':
            return False
        else:
            return True

    ############################################################
    #
    #    Address 系
    #
    ############################################################

    def enableStaticNat(self, addressid, virtualmachineid):
        result = self._sync_request('enableStaticNat',
                                    ipaddressid=addressid,
                                    virtualmachineid=virtualmachineid)

        if result.get('success', '').lower() != 'true':
            return False
        else:
            return True

    def associateAddress(self, zoneid=None):

        #渡されてなければデフォルトゾーン
        if zoneid is None:
            zoneid = self.describeAvailabilityZones()[0]["id"]

        result = self._sync_request('associateIpAddress', zoneid=zoneid)

        addressid = result['id']
        return addressid

    def disassociateAddress(self, addressid):
        result = self._async_request('disassociateIpAddress', id=addressid)

        if result['success'] != 'true':
            return False
        else:
            return True

    def disableStaticNat(self, addressid):
        result = self._async_request('disableStaticNat', ipaddressid=addressid)

        if result['success'] != 'true':
            return False
        else:
            return True

    ############################################################
    #
    #    KeyPair 系
    #
    ############################################################

    def createKeyPair(self, keyName):
        result = self._sync_request('createSSHKeyPair', name=keyName)

        keyPair = result['keypair']
        return keyPair

    def deleteKeyPair(self, keyName):
        result = self._sync_request('deleteSSHKeyPair', name=keyName)

        if result.get('success', '').lower() != 'true':
            return False
        else:
            return True

    def registerSSHKeyPair(self, keyName, keyMaterial):
        result = self._sync_request('registerSSHKeyPair',
                                    name=keyName,
                                    publickey=keyMaterial)

        keypair = result['keypair']
        keyFingerprint = keypair['fingerprint']

        return keyFingerprint

    ############################################################
    #
    #    Snapshot 系
    #
    ############################################################

    def createSnapshot(self, volumeId):
        result = self._async_request('createSnapshot', volumeid=volumeId)

        snapshot = result['snapshot']
        return snapshot

    def deleteSnapshot(self, snapshotId):
        result = self._async_request('deleteSnapshot', id=snapshotId)

        if result['success'] != 'true':
            return False
        else:
            return True

    ############################################################
    #
    #    Tags 系
    #
    ############################################################

    #存在しません

    ############################################################
    #
    #    その他
    #
    ############################################################
    def getPasswordData(self, instanceId):
        try:
            result = self._sync_request('getVMPassword', id=instanceId)
            password = result['password']
            encryptedpassword = password['encryptedpassword']
        except Exception:
            raise IaasException("EPROCESS-000721", [
                instanceId,
            ])

        return encryptedpassword

    ############################################################
    #
    #    LoadBalancer 操作系
    #
    ############################################################

    ALGORITHM_ROUND_ROBIN = 'roundrobin'
    ALGORITHM_LEAST_CONNECTIONS = 'leastconn'

    def createLoadBalancer(self,
                           name,
                           algorithm=None,
                           port=80,
                           private_port=None,
                           zoneid=None,
                           addressid=None):

        if algorithm is None:
            algorithm = self.ALGORITHM_ROUND_ROBIN
        if zoneid is None:
            zoneid = self.describeAvailabilityZones()[0]['id']
        else:
            zoneid = zoneid

        if private_port is None:
            private_port = port

        if addressid is None:
            result = self._async_request('associateIpAddress', zoneid=zoneid)
            addressid = result['ipaddress']['id']

        result = self._sync_request(
            'createLoadBalancerRule',
            algorithm=algorithm,
            name=name,
            privateport=private_port,
            publicport=port,
            publicipid=addressid,
        )

        balancerid = result['id']
        balancer = self.describeLoadBalancer(balancerid)

        return balancer

    def deleteLoadBalancer(self, loadBalancerid):
        balancer = self.describeLoadBalancer(loadBalancerid)

        self._async_request('deleteLoadBalancerRule', id=balancer.id)
        self._async_request('disassociateIpAddress',
                            id=balancer.ex_public_ip_id)

    def attach_members(self, loadBalancerid, virtualmachineids):
        for virtualmachineid in virtualmachineids:
            self._async_request('assignToLoadBalancerRule',
                                id=loadBalancerid,
                                virtualmachineids=virtualmachineid)

        return True

    def detach_members(self, loadBalancerid, virtualmachineids):
        for virtualmachineid in virtualmachineids:
            self._async_request('removeFromLoadBalancerRule',
                                id=loadBalancerid,
                                virtualmachineids=virtualmachineid)
        return True

    def _to_balancer(self, obj):
        balancer = LoadBalancer(id=obj['id'],
                                name=obj['name'],
                                state=obj['state'],
                                ip=obj['publicip'],
                                port=obj['publicport'],
                                driver=self.connection.driver)
        balancer.ex_private_port = obj['privateport']
        balancer.ex_public_ip_id = obj['publicipid']
        return balancer

    def _to_member(self, obj, port):
        return Member(id=obj['id'], ip=obj['nic'][0]['ipaddress'], port=port)
class ec2LoadBalancercontroller(object):

    logger = IaasLogger()
    client = None
    conn = None
    platforminfo = None

    STOPPED = "STOPPED"
    STARTING = "STARTING"
    RUNNING = "RUNNING"
    STOPPING = "STOPPING"
    CONFIGURING = "CONFIGURING"
    WARNING = "WARNING"

    STATUS={
        STOPPED:STOPPED,
        RUNNING:RUNNING,
        STOPPING:STOPPING,
        CONFIGURING:CONFIGURING,
        WARNING:WARNING,
    }



    def __init__(self, platforminfo, ec2iaasclientLb, conn):
        self.client = ec2iaasclientLb
        self.conn = conn
        self.platforminfo = platforminfo

    def getStatusString(self, key):
        if not key:
            return "STOPPED"

        value = self.STATUS[key]
        if value != None:
            return value
        return "STOPPED"


    def createLoadBalancer(self, farmNo, loadBalancerNo, availabilityZones, subnets, groupmap) :
        tableAWSLB = self.conn.getTable("AWS_LOAD_BALANCER")
        awsLoadBalancer = self.conn.selectOne(tableAWSLB.select(tableAWSLB.c.LOAD_BALANCER_NO==loadBalancerNo))

        # ロードバランサ作成情報
        loadBalancerName = awsLoadBalancer["NAME"]

        # 内部ロードバランサ
        internal = awsLoadBalancer["INTERNAL"]

        # デフォルトゾーンの特定 デフォルト1件目
        availabilityZone = None
        for zone in availabilityZones:
            availabilityZone = zone.name

        #セキュリティグループ
        securityGroups = []
        if (isNotEmpty(awsLoadBalancer["SECURITY_GROUPS"])):
            securityGroups = awsLoadBalancer["SECURITY_GROUPS"].split(",")

        #サブネットID
        subnetIds = []
        if (isNotEmpty(awsLoadBalancer["SUBNET_ID"])):
            subnetIds = awsLoadBalancer["SUBNET_ID"].split(",")

        # サブネット(VPC)との関係からセキュリティグループIDを取得
        securityGroupIds = []
        if len(subnetIds) != 0:
            for subnet in subnets:
                if subnetIds[0] == subnet.subnetId:
                    #セキュリティグループID
                    for group in securityGroups:
                        key = group+subnet.vpcId
                        securityGroupIds.append(groupmap[key])


        # ダミーのリスナーの設定  instancePort, instanceProtocol, loadBalancerPort, protocol, sslCertificateId
        listener = Listener("65535", None, "65535","TCP",None)
        listeners = [listener]

        # ロードバランサの作成
        dnsName = self.client.createLoadBalancer(availabilityZone, listeners, loadBalancerName, subnetIds, securityGroupIds, internal)

        #実行ログ
        self.logger.info(None ,"IPROCESS-200111", [awsLoadBalancer["NAME"],])

        # イベントログ出力
        self.conn.debug(farmNo, None, None, None, None, "AwsElbCreate", ["EC2", loadBalancerName] )

        # ダミーのリスナーの削除
        self.client.deleteLoadBalancerListeners(["65535",], loadBalancerName)

        #クロスゾーン負荷分散を有効化
        self.client.modifyLoadBalancer(loadBalancerName)

        #実行ログ
        self.logger.info(None ,"IPROCESS-200226", [awsLoadBalancer["NAME"],])

        # イベントログ出力
        self.conn.debug(farmNo, None, None, None, None, "AwsCrossZoneEnabled", ["EC2", loadBalancerName] )

        # データベース更新
        updateDict = self.conn.selectOne(tableAWSLB.select(tableAWSLB.c.LOAD_BALANCER_NO==loadBalancerNo))
        updateDict["DNS_NAME"] = dnsName
        sql = tableAWSLB.update(tableAWSLB.c.LOAD_BALANCER_NO ==updateDict["LOAD_BALANCER_NO"], values=updateDict)
        self.conn.execute(sql)

        return dnsName;


    def deleteLoadBalancer(self, farmNo, loadBalancerNo) :
        tableAWSLB = self.conn.getTable("AWS_LOAD_BALANCER")
        awsLoadBalancer = self.conn.selectOne(tableAWSLB.select(tableAWSLB.c.LOAD_BALANCER_NO==loadBalancerNo))

        # ロードバランサ名
        loadBalancerName = awsLoadBalancer["NAME"]
        try :
            self.client.deleteLoadBalancer(loadBalancerName);

            #実行ログ
            self.logger.info(None ,"IPROCESS-200112", [awsLoadBalancer["NAME"],])

            # イベントログ出力
            self.conn.debug(farmNo, None, None, None, None, "AwsElbDelete", ["EC2", loadBalancerName] )

        except Exception:
            self.logger.error(traceback.format_exc())

        # データベース更新
        updateDict = self.conn.selectOne(tableAWSLB.select(tableAWSLB.c.LOAD_BALANCER_NO==loadBalancerNo))
        updateDict["DNS_NAME"] = None
        sql = tableAWSLB.update(tableAWSLB.c.LOAD_BALANCER_NO ==updateDict["LOAD_BALANCER_NO"], values=updateDict)
        self.conn.execute(sql)


    def configureListeners(self, farmNo, loadBalancerNo) :
        table = self.conn.getTable("LOAD_BALANCER_LISTENER")
        listeners = self.conn.select(table.select(table.c.LOAD_BALANCER_NO==loadBalancerNo))

        # リスナーの起動・停止処理
        for listener in listeners :
            status = self.getStatusString(listener["STATUS"])
            if isBit(listener["ENABLED"]):
                if status == self.STOPPED :
                    # 有効で停止しているリスナーは処理対象
                    self.startListener(farmNo, loadBalancerNo, listener["LOAD_BALANCER_PORT"])
                elif status == self.RUNNING:
                    # 有効で起動しているリスナーの場合、処理を行わずにフラグを変更する
                    if isBit(listener["CONFIGURE"]):
                        listener["CONFIGURE"] = "0"
                        sql = table.update(and_(table.c.LOAD_BALANCER_NO ==listener["LOAD_BALANCER_NO"], table.c.LOAD_BALANCER_PORT == listener["LOAD_BALANCER_PORT"]), values=listener)
                        self.conn.execute(sql)

            else :
                if (status == self.RUNNING or status == self.WARNING) :
                    # 無効で起動または異常なリスナーは処理対象
                    self.stopListener(farmNo, loadBalancerNo, listener["LOAD_BALANCER_PORT"])
                elif (status == self.STOPPED) :
                    # 無効で停止しているリスナーの場合、処理を行わずにフラグを変更する
                    if isBit(listener["CONFIGURE"]):
                        listener["CONFIGURE"] = "0"
                        sql = table.update(and_(table.c.LOAD_BALANCER_NO ==loadBalancerNo, table.c.LOAD_BALANCER_PORT == listener["LOAD_BALANCER_PORT"]), values=listener)
                        self.conn.execute(sql)

    def startListener(self, farmNo, loadBalancerNo, loadBalancerPort) :
        table = self.conn.getTable("LOAD_BALANCER_LISTENER")
        listener = self.conn.selectOne(table.select(and_(table.c.LOAD_BALANCER_NO==loadBalancerNo, table.c.LOAD_BALANCER_PORT ==loadBalancerPort)))

        try :
            # リスナー作成情報
            tableAWSLB = self.conn.getTable("AWS_LOAD_BALANCER")
            awsLoadBalancer = self.conn.selectOne(tableAWSLB.select(tableAWSLB.c.LOAD_BALANCER_NO==loadBalancerNo))

            sslKey = None

            if (isNotEmpty(listener["SSL_KEY_NO"])):
                # リスナー作成情報
                tableAWSSSL = self.conn.getTable("AWS_SSL_KEY")
                awsSslKey = self.conn.selectOne(tableAWSSSL.select(tableAWSSSL.c.KEY_NO==listener["SSL_KEY_NO"]))
                sslKey = awsSslKey["SSLCERTIFICATEID"]

            # ロードバランサ名
            loadBalancerName = awsLoadBalancer["NAME"]

            # リスナーの設定  instancePort, instanceProtocol, loadBalancerPort, protocol, sslCertificateId
            listeners = [ Listener(listener["SERVICE_PORT"], None, listener["LOAD_BALANCER_PORT"], listener["PROTOCOL"], sslKey),]

            # リスナーの作成
            self.client.createLoadBalancerListeners(listeners, loadBalancerName)

            #実行ログ
            self.logger.info(None ,"IPROCESS-200121", [awsLoadBalancer["NAME"], listener["LOAD_BALANCER_PORT"]])

            # イベントログ出力
            self.conn.debug(farmNo, None, None, None, None, "AwsElbListenerCreate", ["EC2", loadBalancerName, listener["LOAD_BALANCER_PORT"]] )

        except Exception:
            self.logger.error(traceback.format_exc())
            # ステータスを更新
            tableLBL = self.conn.getTable("LOAD_BALANCER_LISTENER")
            updateDict = self.conn.selectOne(tableLBL.select(and_(tableLBL.c.LOAD_BALANCER_NO==loadBalancerNo, tableLBL.c.LOAD_BALANCER_PORT ==loadBalancerPort)))
            updateDict["STATUS"] = self.WARNING
            sql = tableLBL.update(and_(tableLBL.c.LOAD_BALANCER_NO==loadBalancerNo, tableLBL.c.LOAD_BALANCER_PORT ==loadBalancerPort), values=updateDict)
            self.conn.execute(sql)
            raise


        # ステータスを更新
        tableLBL = self.conn.getTable("LOAD_BALANCER_LISTENER")
        updateDict = self.conn.selectOne(table.select(and_(tableLBL.c.LOAD_BALANCER_NO==loadBalancerNo, tableLBL.c.LOAD_BALANCER_PORT ==loadBalancerPort)))
        updateDict["STATUS"] = self.RUNNING
        sql = tableLBL.update(and_(tableLBL.c.LOAD_BALANCER_NO==loadBalancerNo, tableLBL.c.LOAD_BALANCER_PORT ==loadBalancerPort), values=updateDict)
        self.conn.execute(sql)


    def stopListener(self, farmNo, loadBalancerNo, loadBalancerPort) :
        tableLBL = self.conn.getTable("LOAD_BALANCER_LISTENER")
        listener = self.conn.selectOne(tableLBL.select(and_(tableLBL.c.LOAD_BALANCER_NO==loadBalancerNo, tableLBL.c.LOAD_BALANCER_PORT ==loadBalancerPort)))

        try :
            # リスナー削除情報
            table = self.conn.getTable("AWS_LOAD_BALANCER")
            awsLoadBalancer = self.conn.selectOne(table.select(table.c.LOAD_BALANCER_NO==loadBalancerNo))
            # ロードバランサ名
            loadBalancerName = awsLoadBalancer["NAME"]
            # ロードバランサポート
            loadBalancerPort = listener["LOAD_BALANCER_PORT"]
            loadBalancerPorts = [loadBalancerPort,]

            # リスナーの削除
            self.client.deleteLoadBalancerListeners(loadBalancerPorts, loadBalancerName);

            #実行ログ
            self.logger.info(None ,"IPROCESS-200122", [awsLoadBalancer["NAME"], listener["LOAD_BALANCER_PORT"]])

            # イベントログ出力
            self.conn.debug(farmNo, None, None, None, None, "AwsElbListenerDelete", ["EC2", loadBalancerName, listener["LOAD_BALANCER_PORT"]] )

        except Exception, e:
            self.logger.error(traceback.format_exc())
            self.logger.warn(e.getMessage())


        # ステータスを更新
        updateDict = self.conn.selectOne(tableLBL.select(and_(tableLBL.c.LOAD_BALANCER_NO==loadBalancerNo, tableLBL.c.LOAD_BALANCER_PORT ==loadBalancerPort)))
        updateDict["STATUS"] = self.STOPPED
        sql = tableLBL.update(and_(tableLBL.c.LOAD_BALANCER_NO==loadBalancerNo, tableLBL.c.LOAD_BALANCER_PORT ==loadBalancerPort), values=updateDict)
        self.conn.execute(sql)
Ejemplo n.º 21
0
class ec2AddressController(object):
    client = None
    conn = None
    logger = IaasLogger()
    platforminfo = None

    def __init__(self, platforminfo, ec2iaasclient, conn):
        self.client = ec2iaasclient
        self.conn = conn
        self.platforminfo = platforminfo

    def startAddress(self, instanceNo):
        # アドレス情報の取得
        awsAddress = self.getAwsAddress(instanceNo)
        if not awsAddress:
            # アドレス情報がない場合は終了
            return

        if isNotEmpty(awsAddress["INSTANCE_ID"]):
            # インスタンスIDがある場合はスキップ
            return

        addressNo = awsAddress["ADDRESS_NO"]

        # アドレスのステータスチェック
        self.checkAvailableAddress(instanceNo, addressNo)

        # アドレスの関連付け
        self.associateAddress(instanceNo, addressNo)

    def stopAddress(self, instanceNo):
        # アドレス情報の取得
        awsAddress = self.getAwsAddress(instanceNo)

        # アドレス情報がない場合は終了
        if not awsAddress:
            return

        # インスタンスIDがない場合はスキップ
        if isEmpty(awsAddress["INSTANCE_ID"]):
            return

        addressNo = awsAddress["ADDRESS_NO"]

        try:
            # アドレスのステータスチェック
            self.checkAssociatedAddress(instanceNo, addressNo)

            # アドレスの切り離し
            self.disassociateAddress(instanceNo, addressNo)

        except Exception, e:
            # 情報が不整合(インスタンス異常終了時など)の場合、警告ログと後始末のみ行う
            self.logger.warn(e.__repr__())
            table = self.conn.getTable("AWS_ADDRESS")
            updateDict = self.conn.selectOne(
                table.select(table.c.ADDRESS_NO == addressNo))
            updateDict["INSTANCE_ID"] = None
            sql = table.update(table.c.ADDRESS_NO == updateDict["ADDRESS_NO"],
                               values=updateDict)
            self.conn.execute(sql)
Ejemplo n.º 22
0
class MysqlConnector(object):
    logger = IaasLogger()
    session = None
    userNo = None

    LOGLEVEL = {
        "OFF": 100,
        "ERROR": 40,
        "WARN": 30,
        "INFO": 20,
        "DEBUG": 10,
        "ALL": 100,
    }

    def __init__(self, userNo=None):
        #self.logger.info(connectinfo)
        self.session = Session()
        self.userNo = userNo

    def getTable(self, tableName):
        table_object = Table(tableName, METADATA, autoload=True)
        return table_object

    def execute(self, sql, autocommit=True):
        res = self.session.execute(sql)
        if autocommit == True:
            self.commit()

        return res.rowcount

    def selectOne(self, sql):
        res = self.select(sql)
        if res:
            return res[0]
        else:
            return None

    def select(self, sql):
        #res = sql.execute()
        res = self.session.execute(sql)
        values = res.fetchall()
        keys = res.keys()

        rs = []
        for row in values:
            rec = {}
            for i, item in enumerate(keys):
                rec.update({item: row[i]})
            rs.append(rec)

        return rs

    def rollback(self):
        return self.session.rollback()

    def commit(self):
        return self.session.commit()

    def close(self):
        self.session.close()

    #基本的に利用しないでください
    def remakeSession(self):
        self.session.close()
        self.session = Session()

    #####################################################
    #
    #以下イベントログ登録
    #
    #####################################################
    def error(self, farmNo, componentNo, componentName, instanceNo,
              instanceName, code, additions):
        self.beforOutLog("ERROR", farmNo, componentNo, componentName,
                         instanceNo, instanceName, code, additions)

    def warn(self, farmNo, componentNo, componentName, instanceNo,
             instanceName, code, additions):
        self.beforOutLog("WARN", farmNo, componentNo, componentName,
                         instanceNo, instanceName, code, additions)

    def info(self, farmNo, componentNo, componentName, instanceNo,
             instanceName, code, additions):
        self.beforOutLog("INFO", farmNo, componentNo, componentName,
                         instanceNo, instanceName, code, additions)

    def debug(self, farmNo, componentNo, componentName, instanceNo,
              instanceName, code, additions):
        self.beforOutLog("DEBUG", farmNo, componentNo, componentName,
                         instanceNo, instanceName, code, additions)

    def beforOutLog(self, logLevel, farmNo, componentNo, componentName,
                    instanceNo, instanceName, code, additions):

        farmT = Table("FARM", METADATA, autoload=True)
        farm = self.selectOne(farmT.select(farmT.c.FARM_NO == farmNo))
        farmName = None
        if farm is not None:
            farmName = farm["FARM_NAME"]

        userT = Table("USER", METADATA, autoload=True)
        user = self.selectOne(userT.select(userT.c.USER_NO == self.userNo))
        userName = None
        if user is not None:
            userName = user["USERNAME"]

        instanceType = None
        platformNo = None
        if instanceNo is not None:
            instanceT = Table("INSTANCE", METADATA, autoload=True)
            instance = self.selectOne(
                instanceT.select(instanceT.c.INSTANCE_NO == instanceNo))
            if instance is not None:
                platformNo = instance["PLATFORM_NO"]

            isSelect = True
            if isSelect:
                awsinstanceT = Table("AWS_INSTANCE", METADATA, autoload=True)
                awsinstance = self.selectOne(
                    awsinstanceT.select(
                        awsinstanceT.c.INSTANCE_NO == instanceNo))
                if awsinstance is not None:
                    instanceType = awsinstance["INSTANCE_TYPE"]
                    isSelect = False

            if isSelect:
                csinstanceT = Table("CLOUDSTACK_INSTANCE",
                                    METADATA,
                                    autoload=True)
                csinstance = self.selectOne(
                    csinstanceT.select(
                        csinstanceT.c.INSTANCE_NO == instanceNo))
                if csinstance is not None:
                    instanceType = csinstance["INSTANCE_TYPE"]
                    isSelect = False

            if isSelect:
                vminstanceT = Table("VMWARE_INSTANCE", METADATA, autoload=True)
                vminstance = self.selectOne(
                    vminstanceT.select(
                        vminstanceT.c.INSTANCE_NO == instanceNo))
                if vminstance is not None:
                    instanceType = vminstance["INSTANCE_TYPE"]
                    isSelect = False

            if isSelect:
                nifinstanceT = Table("NIFTY_INSTANCE", METADATA, autoload=True)
                nifinstance = self.selectOne(
                    nifinstanceT.select(
                        nifinstanceT.c.INSTANCE_NO == instanceNo))
                if nifinstance is not None:
                    instanceType = nifinstance["INSTANCE_TYPE"]
                    isSelect = False

        self.outLog(logLevel, self.userNo, userName, farmNo, farmName,
                    componentNo, componentName, instanceNo, instanceName, code,
                    instanceType, platformNo, additions)

    def outLog(self, logLevel, userNo, userName, farmNo, farmName, componentNo,
               componentName, instanceNo, instanceName, code, instanceType,
               platformNo, additions):
        # イベントログメッセージの取得
        message = getMassage(code, additions)

        log_table = Table("EVENT_LOG", METADATA2, autoload=True)
        log_table.insert({
            "LOG_NO": None,
            "LOG_DATE": datetime.datetime.today(),
            "LOG_LEVEL": self.LOGLEVEL[logLevel],
            "USER_NO": userNo,
            "USER_NAME": userName,
            "FARM_NO": farmNo,
            "FARM_NAME": farmName,
            "COMPONENT_NO": componentNo,
            "COMPONENT_NAME": componentName,
            "INSTANCE_NO": instanceNo,
            "INSTANCE_NAME": instanceName,
            "MESSAGE_CODE": code,
            "MESSAGE": message,
            "INSTANCE_TYPE": instanceType,
            "PLATFORM_NO": platformNo
        }).execute()
Ejemplo n.º 23
0
class EC2Controller(IaasController):

    logger = IaasLogger()

    conn = None
    accessInfo = None

    client = None
    clientLb = None
    instancecontroller = None
    volumecontroller = None
    addresscontroller = None
    loadBalancercontroller = None
    othercontroller = None

    def __init__(self, conn, accessInfo, platforminfo, isLb = False):
        self.conn = conn
        self.accessInfo = accessInfo
        self.client = EC2IaasClient(platforminfo, accessInfo["USER_NAME"], accessInfo["ACCESS_ID"], accessInfo["SECRET_KEY"])

        #コントローラ作成
        self.instancecontroller = ec2InstanceController(platforminfo, self.client, self.conn)
        self.volumecontroller   = ec2VolumController(platforminfo, self.client, self.conn)
        self.addresscontroller  = ec2AddressController(platforminfo, self.client, self.conn)
        self.othercontroller    = ec2OtherController(platforminfo, self.client, self.conn)

        if isLb:
            #self.clientLb = ec2iaasclientLB(userInfo.getAccessId(), userInfo.getSecretKey)
            self.clientLb = EC2IaasClientLB(platforminfo, accessInfo["USER_NAME"], accessInfo["ACCESS_ID"], accessInfo["SECRET_KEY"])
            #コントローラ作成
            self.loadBalancercontroller = ec2LoadBalancercontroller(platforminfo, self.clientLb, self.conn)

    def __del__(self):
        self.conn.rollback()
        self.conn.close()

    def startInstance(self, instanceNo):

        # インスタンスに関する処理   TODO タイムアウトリトライは未実装
        try:
            self.instancecontroller.startInstance(instanceNo)
        except Exception:
            self.logger.error(traceback.format_exc())
            raise

        # ボリュームに関する処理
        table = self.conn.getTable("AWS_VOLUME")
        volumes = self.conn.select(table.select(table.c.INSTANCE_NO==instanceNo))
        for volume in volumes:
            if isNotEmpty(volume["COMPONENT_NO"]):
                # コンポーネント番号がある場合はスキップ
                continue
            #Volumeスタート
            self.volumecontroller.startVolume(instanceNo, volume["VOLUME_NO"])

        # アドレスに関する処理
        self.addresscontroller.startAddress(instanceNo)

        self.conn.commit()
        return "RESULT:TRUE"


    def stopInstance(self, instanceNo):

        try :
            # アドレスに関する処理
            self.addresscontroller.stopAddress(instanceNo)
        except Exception:
            self.logger.error(traceback.format_exc())

        try :
            # インスタンスに関する処理
            self.instancecontroller.stopInstance(instanceNo);
        except Exception:
            self.logger.error(traceback.format_exc())

        try :
            # ボリュームに関する処理
            tableAWSVOL = self.conn.getTable("AWS_VOLUME")
            volumes = self.conn.select(tableAWSVOL.select(tableAWSVOL.c.INSTANCE_NO==instanceNo))

            #PCC_INSTANCE 取得
            tableINS = self.conn.getTable("INSTANCE")
            pccInstance = self.conn.selectOne(tableINS.select(tableINS.c.INSTANCE_NO==instanceNo))

            #イメージの取得  再考の余地あり
            image = getImage(pccInstance["IMAGE_NO"])

            for awsVolume in volumes:
                if (image["ebsImage"]=="true"):
                    self.volumecontroller.stopVolume(instanceNo, awsVolume["VOLUME_NO"])
                else:
                    if (isNotEmpty(awsVolume["VOLUME_ID"]) and isNotEmpty(awsVolume["INSTANCE_ID"])):
                        updateDict = self.conn.selectOne(tableAWSVOL.select(tableAWSVOL.c.VOLUME_NO==awsVolume["VOLUME_NO"]))
                        updateDict["STATUS"] = None
                        updateDict["INSTANCE_ID"] = None
                        sql = tableAWSVOL.update(tableAWSVOL.c.VOLUME_NO ==updateDict["VOLUME_NO"], values=updateDict)
                        self.conn.execute(sql)
        except Exception:
            self.logger.error(traceback.format_exc())

        self.conn.commit()
        return "RESULT:TRUE"


    def terminateInstance(self, instanceId):

        #1度も起動されていない
        if instanceId is None:
            return

        #AWS_INSTANCE 取得
        tableAWSINS = self.conn.getTable("AWS_INSTANCE")
        awsInstance = self.conn.selectOne(tableAWSINS.select(tableAWSINS.c.INSTANCE_ID==instanceId))

        # インスタンスの停止
        change = self.client.terminateInstance(instanceId);

        # データベース更新
        awsInstance["STATUS"] = change["name"]
        sql = tableAWSINS.update(tableAWSINS.c.INSTANCE_NO ==awsInstance["INSTANCE_NO"], values=awsInstance)
        self.conn.execute(sql)

        self.conn.commit()
        return "RESULT:TRUE"

    def startVolume(self, instanceNo, volumeNo):
        self.volumecontroller.startVolume(instanceNo, volumeNo)
        self.conn.commit()
        return "RESULT:TRUE"

    def stopVolume(self, instanceNo, volumeNo):
        self.volumecontroller.stopVolume(instanceNo, volumeNo)
        self.conn.commit()
        return "RESULT:TRUE"

    def deleteVolume(self, volumeId):
        self.client.deleteVolume(volumeId)
        self.conn.commit()
        return "RESULT:TRUE"

    def startLoadBalancer(self, loadBalancerNo):
        tableLB = self.conn.getTable("LOAD_BALANCER")
        loadBalancer = self.conn.selectOne(tableLB.select(tableLB.c.LOAD_BALANCER_NO==loadBalancerNo))


        # ゾーン情報の取得
        zones = self.client.describeAvailabilityZones()

        # サブネットID
        subnets = self.client.describeSubnets()

        # セキュリティグループ
        groups = self.client.describeSecurityGroups()
        groupmap = {}
        for group in groups:
            if group.vpcId is not None:
                key = group.groupName+group.vpcId
                groupmap.update({key:group.groupId})

        # ロードバランサの作成
        self.loadBalancercontroller.createLoadBalancer(loadBalancer["FARM_NO"], loadBalancerNo, zones, subnets, groupmap)

        # DNSサーバへの追加    ここは未定
        #self.loadBalancercontroller.addDns(loadBalancerNo)
        self.conn.commit()
        return "RESULT:TRUE"

    def stopLoadBalancer(self, loadBalancerNo):
        tableLB = self.conn.getTable("LOAD_BALANCER")
        loadBalancer = self.conn.selectOne(tableLB.select(tableLB.c.LOAD_BALANCER_NO==loadBalancerNo))

        # DNSサーバからの削除
        #self.loadBalancercontroller.deleteDns(loadBalancerNo);

        # ロードバランサの削除
        self.loadBalancercontroller.deleteLoadBalancer(loadBalancer["FARM_NO"],loadBalancerNo)
        self.conn.commit()
        return "RESULT:TRUE"

    def configureLoadBalancer(self, loadBalancerNo):
        table = self.conn.getTable("LOAD_BALANCER")
        loadBalancer = self.conn.selectOne(table.select(table.c.LOAD_BALANCER_NO==loadBalancerNo))

        # リスナーの設定
        try :
            self.loadBalancercontroller.configureListeners(loadBalancer["FARM_NO"], loadBalancerNo)
        except Exception:
            self.logger.error(traceback.format_exc())
            # ロードバランサが無効な場合は例外を握りつぶす
            if isBit(loadBalancer["ENABLED"]):
                raise

        # ヘルスチェックの設定
        try :
            self.loadBalancercontroller.configureHealthCheck(loadBalancer["FARM_NO"], loadBalancerNo)
        except Exception:
            self.logger.error(traceback.format_exc())
            # ロードバランサが無効な場合は例外を握りつぶす
            if isBit(loadBalancer["ENABLED"]):
                raise

        # セキュリティグループの設定
        try :
            # サブネットID
            subnets = self.client.describeSubnets()

            # セキュリティグループ
            groups = self.client.describeSecurityGroups()
            groupmap = {}
            for group in groups:
                if group.vpcId is not None:
                    key = group.groupName+group.vpcId
                    groupmap.update({key:group.groupId})

            self.loadBalancercontroller.applySecurityGroupsToLoadBalancer(loadBalancer["FARM_NO"], loadBalancerNo, groupmap, subnets)
        except Exception:
            self.logger.error(traceback.format_exc())
            # ロードバランサが無効な場合は例外を握りつぶす
            if isBit(loadBalancer["ENABLED"]):
                raise

        # インスタンスの振り分け設定
        try :
            self.loadBalancercontroller.configureInstances(loadBalancer["FARM_NO"], loadBalancerNo);
        except Exception:
            self.logger.error(traceback.format_exc())
            # ロードバランサが無効な場合は例外を握りつぶす
            if isBit(loadBalancer["ENABLED"]):
                raise

        self.logger.info(None, "IPROCESS-200106", [loadBalancerNo, loadBalancer["LOAD_BALANCER_NAME"]])

        self.conn.commit()
        return "RESULT:TRUE"


    def allocateAddress(self):
        publicIp = None
        platformNo = self.client.getPlatformNo()

        tablePLAWS = self.conn.getTable("PLATFORM_AWS")
        awsPlatform = self.conn.selectOne(tablePLAWS.select(tablePLAWS.c.PLATFORM_NO==platformNo))

        if awsPlatform["VPC"] == 1:
            #VPC用のElasticIP発行処理呼び出し
            publicIp = self.client.allocateVpcAddress()
        else:
            #ElasticIP発行処理呼び出し
            publicIp = self.client.allocateAddress()

        #イベントログ出力
        self.conn.debug(None, None, None, None, None, "AwsElasticIpAllocate", ["EC2", publicIp])

        #DBへ登録
        table = self.conn.getTable("AWS_ADDRESS")
        sql = table.insert({"ADDRESS_NO":None,
                            "USER_NO":self.accessInfo["USER"],
                            "PLATFORM_NO":platformNo,
                            "PUBLIC_IP":publicIp,
                            "COMMENT":None,
                            "INSTANCE_NO":None,
                            "INSTANCE_ID":None})
        self.conn.execute(sql)

        newAddress = self.conn.selectOne(table.select(table.c.PUBLIC_IP==publicIp))

        self.conn.commit()
        return "RESULT:" + str(newAddress["ADDRESS_NO"])

    def releaseAddress(self, addressNo):
        platformNo = self.client.getPlatformNo()

        tablePLAWS = self.conn.getTable("PLATFORM_AWS")
        awsPlatform = self.conn.selectOne(tablePLAWS.select(tablePLAWS.c.PLATFORM_NO==platformNo))

        table = self.conn.getTable("AWS_ADDRESS")
        address = self.conn.selectOne(table.select(table.c.ADDRESS_NO==addressNo))

        if not address:
            return

        ipaddress = address["PUBLIC_IP"]
        instanceId = address["INSTANCE_ID"]
        instanceNo = address["INSTANCE_NO"]

        if awsPlatform["VPC"] == 1:
            #アドレス情報取得
            address = self.client.describeAddress(ipaddress)
            #VPC用のElasticIP解放処理呼び出し
            self.client.releaseVpcAddress(ipaddress, address.allocationId)
        else:
            #ElasticIP解放処理呼び出し
            self.client.releaseAddress(ipaddress)

        #イベントログ
        self.conn.debug(None, None, None, None, None, "AwsElasticIpRelease", ["EC2", ipaddress])

        #DBから削除
        table.delete(table.c.ADDRESS_NO==addressNo).execute()

        self.conn.commit()
        return "RESULT:TRUE"

    def describeSnapshot(self, snapshotId):
        snapshots = self.othercontroller.describeSnapshot(snapshotId)
        rtString = ''
        for snapshot in snapshots:
            if rtString != '':
                rtString = rtString + "##"

            #とりあえず全部
            rtString = rtString  + snapshot.snapshotId + '#' \
                                 + snapshot.volumeId + '#' \
                                 + snapshot.status + '#' \
                                 + snapshot.startTime + '#' \
                                 + snapshot.progress + '#' \
                                 + snapshot.ownerId + '#' \
                                 + snapshot.volumeSize + '#' \
                                 + snapshot.description + '#' \
                                 + snapshot.tagSet

        self.conn.commit()
        return "RESULT:" + rtString


    def createSnapshot(self, volumeNo):
        self.othercontroller.createSnapshot(volumeNo)
        self.conn.commit()
        return "RESULT:TRUE"

    def deleteSnapshot(self, snapshotNo):
        self.othercontroller.deleteSnapshot(snapshotNo)
        self.conn.commit()
        return "RESULT:TRUE"

    def getPasswordData(self, instanceNo):
        passwordData = self.othercontroller.getPasswordData(instanceNo)
        self.conn.commit()
        return "RESULT:" + passwordData

    def describeKeyPairs(self):
        keypairs = self.client.describeKeyPairs()
        rtString = ''
        for keypair in keypairs:
            if rtString != '':
                rtString = rtString + "##"

            #とりあえず必要な情報のみ返します
            rtString = rtString +  keypair.keyName

        self.conn.commit()
        return "RESULT:" + rtString

    def createKeyPair(self, keyName):
        self.client.createKeyPair(keyName)
        self.conn.commit()
        return "RESULT:TRUE"

    def deleteKeyPair(self, keyName):
        self.client.deleteKeyPair(keyName)
        self.conn.commit()
        return "RESULT:TRUE"

    def importKeyPair(self, keyName, publicKeyMaterial):
        keyPair = self.client.importKeyPair(keyName, publicKeyMaterial)

        keyFingerprint = keyPair.keyFingerprint
        self.conn.commit()
        return "RESULT:" + keyFingerprint

    def describeSecurityGroups(self, vpcid = None):
        groups = self.client.describeSecurityGroups()
        rtString = ''
        for group in groups:
            #VPCIDが一致する物以外は除外
            if vpcid is not None:
                if vpcid != group.vpcId:
                    continue
            #VPCID未入力時はVPCIDが設定されていない物のみ使用
            else:
                if group.vpcId is not None:
                    continue

            if rtString != '':
                rtString = rtString + "##"

            #とりあえず必要な情報のみ返します
            rtString = rtString + group.groupName

        self.conn.commit()
        return "RESULT:" + rtString

    def describeAvailabilityZones(self):
        zones = self.client.describeAvailabilityZones()

        #available
        rtString = ''
        for zone in zones:
            #有効な物のみ利用する
            if zone.zone_state != "available":
                continue

            if rtString != '':
                rtString = rtString + "##"

            #とりあえず必要な情報のみ返します IDに相当するパラメータが無い為NONEを入れておく
            rtString = rtString  + zone.name + "#NONE"
        self.conn.commit()
        #出力として返す
        return "RESULT:" + rtString


    def describeSubnets(self, vpcid = None):
        subnets = self.client.describeSubnets()
        rtString = ''
        for subnet in subnets:
            if vpcid is not None:
                if vpcid != subnet.vpcId:
                    continue

            if rtString != '':
                rtString = rtString + "##"

            #とりあえず必要な情報のみ返します
            rtString = rtString + subnet.subnetId + '#' + subnet.availabilityZone+ '#' + subnet.cidrBlock
        self.conn.commit()
        return "RESULT:" + rtString
Ejemplo n.º 24
0
class ec2VolumController(object):
    logger = IaasLogger()
    client = None
    conn = None
    platforminfo = None

    def __init__(self, platforminfo, ec2iaasclient, conn):
        self.client = ec2iaasclient
        self.conn = conn
        self.platforminfo = platforminfo

    def startVolumes(self, instanceNo):
        # ボリューム情報の取得
        table = self.conn.getTable("AWS_VOLUME")
        volumes = self.conn.select(
            table.select(table.c.INSTANCE_NO == instanceNo))

        for volume in volumes:
            self.startVolume(instanceNo, volume["VOLUME_NO"])

    def startVolume(self, instanceNo, volumeNo):
        table = self.conn.getTable("AWS_VOLUME")
        volume = self.conn.selectOne(
            table.select(table.c.VOLUME_NO == volumeNo))

        # インスタンスIDがある場合はスキップ
        if (isNotEmpty(volume["INSTANCE_ID"])):
            return

        if (isEmpty(volume["VOLUME_ID"])):
            # ボリュームIDがない場合は新規作成
            self.createVolume(instanceNo, volumeNo)

            # ボリュームの作成待ち
            self.waitCreateVolume(instanceNo, volumeNo)

            # ボリュームにタグを付ける
            self.createTag(volumeNo)

        # ボリュームのアタッチ
        self.attachVolume(instanceNo, volumeNo)

        # ボリュームのアタッチ待ち
        self.waitAttachVolume(instanceNo, volumeNo)

    def stopVolumes(self, instanceNo):
        # ボリューム情報の取得
        awsVolumes = self.getAwsVolumes(instanceNo)

        for volume in awsVolumes:
            self.stopVolume(instanceNo, volume["VOLUME_NO"])

    def stopVolume(self, instanceNo, volumeNo):
        table = self.conn.getTable("AWS_VOLUME")
        awsVolume = self.conn.selectOne(
            table.select(table.c.VOLUME_NO == volumeNo))

        # ボリュームIDがない場合はスキップ
        if (isEmpty(awsVolume["VOLUME_ID"])):
            return

        # インスタンスIDがない場合はスキップ
        if (isEmpty(awsVolume["INSTANCE_ID"])):
            return

        try:
            # ボリュームのデタッチ
            self.detachVolume(instanceNo, volumeNo)

            # ボリュームのデタッチ待ち
            self.waitDetachVolume(instanceNo, volumeNo)
        except Exception, e:
            self.logger.error(traceback.format_exc())
            # 情報が不整合(インスタンス異常終了時など)の場合、警告ログと後始末のみ行う
            self.logger.warn(e.massage)

            table = self.conn.getTable("AWS_VOLUME")
            updateDict = self.conn.selectOne(
                table.select(table.c.VOLUME_NO == volumeNo))
            updateDict["STATUS"] = "error"
            updateDict["INSTANCE_ID"] = None
            sql = table.update(table.c.VOLUME_NO == updateDict["VOLUME_NO"],
                               values=updateDict)
            self.conn.execute(sql)
class OpenStackIaasClient:

    logger = IaasLogger()
    platformNo = None
    username = None
    tenant = None
    tenant_id = None
    auth_url = None
    nova = None

    timeout = False
    TIMEOUT = 600

    def __init__(self, platforminfo, username, password):

        self.username = username
        self.platformNo = platforminfo["platformNo"]
        openstackInfo = getOpenStackInfo(self.platformNo)
        self.tenant = openstackInfo['TENANT_NM']
        self.tenant_id = openstackInfo['TENANT_ID']
        self.auth_url = openstackInfo['URL']

        self.logger.debug('username=%s' % (self.username))
        self.logger.debug('password=%s' % (password))
        self.logger.debug('tenant=%s' % (self.tenant))
        self.logger.debug('auth_url=%s' % (self.auth_url))
        self.logger.debug('tenant_id=%s' % (self.tenant_id))
        # NOVAマネージャ作成
        self.nova = nclient(self.username,
                            password,
                            self.tenant,
                            self.auth_url,
                            tenant_id=self.tenant_id)
        # CINDERマネージャ作成
        self.cinder = cclient(self.username,
                              password,
                              self.tenant,
                              self.auth_url,
                              tenant_id=self.tenant_id)

        signal.signal(signal.SIGALRM, self._taskTimeout)

    def _taskTimeout(self, signum, frame):
        self.timeout = True
        return

    def _setTimeout(self, TIMEOUT):
        self.timeout = False
        signal.alarm(TIMEOUT)

    def _resetTimeout(self):
        self.timeout = False

    def _isTimeout(self):
        return self.timeout

    def _findServerById(self, instanceId):
        try:
            instanceObj = self.nova.servers.get(instanceId)
        except:
            self.logger.error(traceback.format_exc())
            raise
        else:
            return instanceObj

    def _getVirtualMachine(self, instanceId):
        try:
            instanceObj = self._findServerById(instanceId)
        except:
            self.logger.error(traceback.format_exc())
            raise
        else:
            return instanceObj

    def _waitServerStatus(self, serverId, waitStatus, timeout=TIMEOUT):
        SLEEP = 10
        self._setTimeout(timeout)
        while True:
            time.sleep(SLEEP)
            instanceObj = self._getVirtualMachine(serverId)
            status = instanceObj.status
            self.logger.debug('      Status: %s' % (status))
            if status == waitStatus:
                return instanceObj
            elif status == 'ERROR':
                return instanceObj
            if self._isTimeout() is True:
                self._resetTimeout()
                return instanceObj

    def _findFlavorById(self, flavorId):
        try:
            flavorList = self.nova.flavors.list()
        except:
            self.logger.error(traceback.format_exc())
        for flavorObject in flavorList:
            fId = flavorObject.id
            if fId == flavorId:
                flavorName = flavorObject.name
                self.logger.debug('      Flavor Name: %s' % (flavorName))
                return flavorObject
        else:
            return None

    def _findFlavorByName(self, flavorName):
        try:
            flavorList = self.nova.flavors.list()
        except:
            self.logger.error(traceback.format_exc())
        for flavorObject in flavorList:
            fNm = flavorObject.name
            if fNm == flavorName:
                flavorId = flavorObject.id
                self.logger.debug('      Flavor Name: %s' % (flavorName))
                return flavorObject
        else:
            return None

    def _findImageById(self, imageId):
        try:
            imageList = self.nova.images.list()
        except:
            self.logger.error(traceback.format_exc())
        for imageObject in imageList:
            iId = imageObject.id
            if iId == imageId:
                imageName = imageObject.name
                self.logger.debug('      Image Name: %s' % (imageName))
                return imageObject
        else:
            return None

    def getVirtualMachineStatus(self, instanceId):
        try:
            instanceObj = self._getVirtualMachine(instanceId)
        except:
            # NotFound or any other exception
            self.logger.error(traceback.format_exc())
            raise
        status = instanceObj.status
        self.logger.debug('      Instance Status: %s' % (status))
        return status

    def deleteVirtualMachine(self, serverId):
        instanceObj = self._findServerById(serverId)
        # VM削除
        try:
            novaResponse = self.nova.servers.delete(instanceObj)
        except:
            self.logger.error(traceback.format_exc())
            raise

        return None

    def stopVirtualMachine(self, serverId):
        instanceObj = self._findServerById(serverId)
        # VM停止
        try:
            novaResponse = self.nova.servers.stop(instanceObj)
        except:
            # BadRequest: Instance xxx in vm_state stopped. Cannot stop while the instance is in this state.
            #             (HTTP 400) (Request-ID: xxx)
            self.logger.error(traceback.format_exc())
            raise

        # 停止完了まで待つ
        instanceObj = self._waitServerStatus(serverId, 'SHUTOFF')
        status = instanceObj.status
        if status != 'SHUTOFF' and status != 'ERROR':
            # タイムアウト
            self.logger.error('The operation timed out.')
            # 呼び出し側で例外を補足して、異なる例外を送出しているため、下記例外は失われる。
            raise IaasException("EPROCESS-001011")

        return instanceObj

    def startVirtualMachine(self, serverId):
        instanceObj = self._findServerById(serverId)
        # VM起動
        try:
            novaResponse = self.nova.servers.start(instanceObj)
        except:
            self.logger.error(traceback.format_exc())
            raise

        # 起動完了まで待つ
        instanceObj = self._waitServerStatus(serverId, 'ACTIVE')
        status = instanceObj.status
        if status != 'ACTIVE' and status != 'ERROR':
            # タイムアウト
            self.logger.error('The operation timed out.')
            # 呼び出し側で例外を補足して、異なる例外を送出しているため、下記例外は失われる。
            raise IaasException("EPROCESS-001011")

        return instanceObj

    def createVirtualMachine(self, serverName, flavorNm, imageId,
                             availabilityZoneId, networkId, userData,
                             securityGroupId, keyName):
        # フレーバーIDからフレーバーオブジェクトへの変換
        flavorObject = self._findFlavorByName(flavorNm)
        if flavorObject is None:
            self.logger.error('      Flavor Not Found: %s' % (flavorId))
            raise IaasException("EPROCESS-001001")

        # イメージIDからイメージオブジェクトへの変換
        imageObject = self._findImageById(imageId)
        if imageObject is None:
            self.logger.error('      Image Not Found: %s' % (imageId))
            raise IaasException("EPROCESS-001001")

        # NICリストの作成
        nics = [{"net-id": networkId, "v4-fixed-ip": "", "port-id": ""}]

        # セキュリティグループリストの作成
        securityGroupList = [securityGroupId]

        # VM作成
        try:
            novaResponse = self.nova.servers.create(
                serverName,
                flavor=flavorObject,
                image=imageObject,
                availability_zone=availabilityZoneId,
                nics=nics,
                userdata=userData,
                security_groups=securityGroupList,
                key_name=keyName)
        except:
            self.logger.error(traceback.format_exc())
            raise

        # 作成完了まで待つ
        serverId = novaResponse.id
        instanceObj = self._waitServerStatus(serverId, 'ACTIVE')
        status = instanceObj.status
        if status != 'ACTIVE' and status != 'ERROR':
            # タイムアウト
            self.logger.error('The operation timed out.')
            # 呼び出し側で例外を補足して、異なる例外を送出しているため、下記例外は失われる。
            raise IaasException("EPROCESS-001011")

        return instanceObj

    def createVolume(self, name, availabilityZone, size=None, snapshotId=None):
        #volume = self.nova.volumes.create(size=1, display_name='test02')
        volume = self.cinder.volumes.create(size=size, display_name=name)
        return volume

    def attachVolume(self, volumeId, instanceId, device):
        #self.cinder.volumes.attach(volumeId, instanceId, device)
        self.nova.volumes.create_server_volume(instanceId, volumeId, device)

    def detachVolume(self, instanceId, volumeId):
        #self.cinder.volumes.detach(volumeId)
        self.nova.volumes.delete_server_volume(instanceId, volumeId)

    def deleteVolume(self, volumeId):
        self.cinder.volumes.delete(volumeId)

    def describeVolume(self, volumeId):
        volume = self.cinder.volumes.get(volumeId)
        return volume

    def describeSecurityGroups(self, vpcid=None):
        secgroups = self.nova.security_groups.list()
        return secgroups

    def describeAvailabilityZones(self):
        zones = self.nova.availability_zones.list(detailed=False)
        return zones

    def describeNetworks(self):
        networks = self.nova.networks.list()
        return networks

    def describeFlavors(self):
        flavorList = self.nova.flavors.list()
        return flavorList

    def describeKeyPairs(self):
        keypairList = self.nova.keypairs.list()
        return keypairList

    def createKeyPair(self, keyName, publicKeyMaterial):
        self.nova.keypairs.create(name=keyName, public_key=publicKeyMaterial)
        return
Ejemplo n.º 26
0
class EC2IaasClient(EC2IaasNodeDriver):

    logger = IaasLogger()
    platformNo = None
    debugout = True
    username = None

    def __init__(self, platforminfo, username, key, secret=None):

        self.platformNo = platforminfo["platformNo"]
        self.username = username
        useProxy = platforminfo["proxy"]
        #プロキシ利用
        if useProxy == 1:
            useProxy = True
        else:
            useProxy = False

        #リュージョン取得
        awsInfo = getAwsInfo(self.platformNo)
        region = awsInfo["region"]

        super(EC2IaasClient, self).__init__(region=region,
                                            key=key,
                                            secret=secret,
                                            useProxy=useProxy)

    ############################################################
    #
    #    基礎データ
    #
    ############################################################
    def getPlatformNo(self):
        return self.platformNo

    def setPlatformNo(self, platformNo):
        self.platformNo = platformNo

    def getUsername(self):
        return self.username

    ############################################################
    #
    #    参照系  describe
    #
    ############################################################

    def describeImages(self, location=None):
        return super(EC2IaasClient, self).list_images(location)

    def describeImage(self, imageId):
        params = {'Action': 'DescribeImages', 'ImageId.0': imageId}

        #ここで利用する_to_imagesは拡張版です
        images = self._to_images(
            self.connection.request(self.path, params=params).object)

        if not images or len(images) == 0:
            #インスタンスが存在しない場合
            return None

        return images[0]

    #list_nodesとして提供されているが、機能としてはインスタンス指定を利用がいいか?
    def describeInstances(self, instanceid=None):
        params = {'Action': 'DescribeInstances'}

        #任意パラメータ
        if instanceid != None:
            params.update({'InstanceId.0': instanceid})

        elem = self.connection.request(self.path, params=params).object

        nodes = []
        for rs in findall(element=elem,
                          xpath='reservationSet/item',
                          namespace=NAMESPACE):
            groups = []
            for g in findall(
                    element=rs,
                    xpath=
                    'instancesSet/item/networkInterfaceSet/item/groupSet/item',
                    namespace=NAMESPACE):
                groups.append(
                    findattr(element=g, xpath='groupId', namespace=NAMESPACE))

            nodes += self._to_nodes(rs, 'instancesSet/item', groups)
        nodes_elastic_ips_mappings = self.ex_describe_addresses(nodes)
        for node in nodes:
            node.public_ip.extend(nodes_elastic_ips_mappings[node.id])
        return nodes

    #list_nodesとして提供されているものをそのまま使って必要な物だけ
    def describeInstance(self, instanceid):
        nodes = self.describeInstances(instanceid)

        if not nodes or len(nodes) == 0:
            #インスタンスが存在しない場合
            raise IaasException("EPROCESS-000101", [
                instanceid,
            ])

        if len(nodes) > 1:
            #インスタンスを複数参照できた場合
            raise IaasException("EPROCESS-000102", [
                instanceid,
            ])

        return nodes[0]

    #LibCloudで提供されていない為独自実装
    def describeVolume(self, volumeId):
        volumes = self.describeVolumes(volumeId)

        if not volumes or len(volumes) == 0:
            #インスタンスが存在しない場合
            raise IaasException("EPROCESS-000110", [
                volumeId,
            ])

        if len(volumes) > 1:
            #インスタンスを複数参照できた場合
            raise IaasException("EPROCESS-000111", [
                volumeId,
            ])

        return volumes[0]

    #LibCloudで提供されていない為独自実装
    def describeVolumes(self, volumeId=None):
        params = {'Action': 'DescribeVolumes'}
        #任意パラメータ
        if volumeId != None:
            params.update({'VolumeId.0': volumeId})

        elem = self.connection.request(self.path, params=params).object

        volumes = []
        for rs in findall(element=elem,
                          xpath='volumeSet/item',
                          namespace=NAMESPACE):
            volumes.append(self._to_volumes(rs))

        return volumes

    def describeAddress(self, publicIp):
        address = self.describeAddresses(publicIp)

        if not address or len(address) == 0:
            #アドレスが存在しない場合
            raise IaasException("EPROCESS-000117", [
                publicIp,
            ])

        if len(address) > 1:
            #アドレスを複数参照できた場合
            raise IaasException("EPROCESS-000118", [
                publicIp,
            ])

        return address[0]

    def describeVpcAddress(self, publicIp=None):
        params = {'Action': 'DescribeAddresses'}
        #任意パラメータ
        if publicIp != None:
            params.update({'PublicIp.0': publicIp})

        elem = self.connection.request(self.path, params=params).object

        address = []
        for rs in findall(element=elem,
                          xpath='addressesSet/item',
                          namespace=NAMESPACE):
            address.append(self._to_vpcaddress(rs))

        if not address or len(address) == 0:
            #アドレスが存在しない場合
            raise IaasException("EPROCESS-000117", [
                publicIp,
            ])

        if len(address) > 1:
            #アドレスを複数参照できた場合
            raise IaasException("EPROCESS-000118", [
                publicIp,
            ])

        return address[0]

    #LibCloudで提供されているDescribeAddressesラップ関数は利用形態がマッチしないので独自実装とする
    #本来はpublicIpを省略する事も可能だが用途的に固定する
    def describeAddresses(self, publicIp=None):
        params = {'Action': 'DescribeAddresses'}
        #任意パラメータ
        if publicIp != None:
            params.update({'PublicIp.0': publicIp})

        elem = self.connection.request(self.path, params=params).object

        address = []
        for rs in findall(element=elem,
                          xpath='addressesSet/item',
                          namespace=NAMESPACE):
            address.append(self._to_address(rs))

        return address

    #LibCloudで提供されているdescribeKeyPairsラップ関数はNameの入力が必須である為用途が異なる為、独自実装
    def describeKeyPairs(self):
        params = {'Action': 'DescribeKeyPairs'}

        elem = self.connection.request(self.path, params=params).object

        keypairs = []
        for rs in findall(element=elem,
                          xpath='keySet/item',
                          namespace=NAMESPACE):
            keypairs.append(self._to_keypair(rs))

        return keypairs

    #LibCloudで提供されていない為独自実装
    def describeSecurityGroups(self, groupName=None, vpcId=None):
        #GroupName, GroupId, Filter(name/Value)で絞る事ができるがPCCでは利用しないデフォルト検索を提供する
        params = {'Action': 'DescribeSecurityGroups'}

        #任意パラメータ
        if groupName != None:
            params.update({'Filter.0.Name': 'group-name'})
            params.update({'Filter.0.Value.0': groupName})

        if vpcId != None:
            params.update({'Filter.1.Name': 'vpc-id'})
            params.update({'Filter.1.Value.0': vpcId})

        elem = self.connection.request(self.path, params=params).object

        securityGroups = []
        for rs in findall(element=elem,
                          xpath='securityGroupInfo/item',
                          namespace=NAMESPACE):
            securityGroups.append(self._to_securityGroup(rs))

        return securityGroups

    #ex_list_availability_zonesとして提供されているものをラップ
    def describeAvailabilityZones(self, only_available=True):
        return super(EC2IaasClient,
                     self).ex_list_availability_zones(only_available)

    #LibCloudで提供されていない為独自実装
    def describeSnapshot(self, snapshotId):
        snapshots = self.describeSnapshots(snapshotId)

        if not snapshots or len(snapshots) == 0:
            #アドレスが存在しない場合
            raise IaasException("EPROCESS-000122", [
                snapshotId,
            ])

        if len(snapshots) > 1:
            #アドレスを複数参照できた場合
            raise IaasException("EPROCESS-000123", [
                snapshotId,
            ])

        return snapshots[0]

    #LibCloudで提供されていない為独自実装
    def describeSnapshots(self, snapshotId=None):
        #Owner, RestorableBy, Filter(name/Value)で絞る事ができるが制限する
        params = {'Action': 'DescribeSnapshots'}
        #任意パラメータ
        if snapshotId != None:
            params.update({'SnapshotId': snapshotId})

        elem = self.connection.request(self.path, params=params).object

        snapshots = []
        for rs in findall(element=elem,
                          xpath='snapshotSet/item',
                          namespace=NAMESPACE):
            snapshots.append(self._to_snapshot(rs))

        return snapshots

    def describeRegions(self, regionName=None):
        params = {'Action': 'DescribeRegions'}
        #任意パラメータ
        if regionName != None:
            params.update({'RegionName': regionName})

        elem = self.connection.request(self.path, params=params).object

        regionInfos = []
        for rs in findall(element=elem,
                          xpath='regionInfo/item',
                          namespace=NAMESPACE):
            regionInfos.append(self._to_regionInfo(rs))

        return regionInfos

    def describeVpcs(self, vpcId=None):
        params = {'Action': 'DescribeVpcs'}
        #任意パラメータ
        if vpcId != None:
            params.update({'VpcId': vpcId})

        elem = self.connection.request(self.path, params=params).object

        vpcInfos = []
        for rs in findall(element=elem,
                          xpath='vpcSet/item',
                          namespace=NAMESPACE):
            vpcInfos.append(self._to_vpcInfo(rs))

        return vpcInfos

    def describeSubnets(self, subnetId=None):
        params = {'Action': 'DescribeSubnets'}
        #任意パラメータ
        if subnetId != None:
            params.update({'SubnetId': subnetId})

        elem = self.connection.request(self.path, params=params).object

        subnetInfos = []
        for rs in findall(element=elem,
                          xpath='subnetSet/item',
                          namespace=NAMESPACE):
            subnetInfos.append(self._to_subnetInfo(rs))

        return subnetInfos

    def describeTags(self, instanceId=None):
        params = {'Action': 'DescribeTags'}
        #任意パラメータ
        if instanceId != None:
            params.update({'Filter.0.Name': 'resource-id'})
            params.update({'Filter.0.Value.0': instanceId})

        elem = self.connection.request(self.path, params=params).object

        tagSets = []
        for rs in findall(element=elem,
                          xpath='tagSet/item',
                          namespace=NAMESPACE):
            tagSets.append(self._to_tagSet(rs))

        return tagSets

    ############################################################
    #
    #    Instance 系
    #
    ############################################################
    def runInstances(self, groupmap, **kwargs):
        params = {
            'Action': 'RunInstances',
            'ImageId': kwargs.get('imageId'),
            'InstanceType': kwargs.get('instanceType'),
            'MinCount': kwargs.get('ex_mincount', '1'),
            'MaxCount': kwargs.get('ex_maxcount', '1'),
        }

        isGroupID = False
        isPrivateIp = False
        if 'subnetId' in kwargs and kwargs['subnetId'] is not None:
            params['SubnetId'] = kwargs['subnetId']
            #サブネットありの場合はセキュリティグループはIDを使う
            isGroupID = True
            isPrivateIp = True

        if 'securityGroup' in kwargs:
            if kwargs['securityGroup'] is not None:
                securityGroups = kwargs['securityGroup']
                for sig in range(len(securityGroups)):
                    if isGroupID:
                        params['SecurityGroupId.%d' %
                               (sig + 1, )] = groupmap[securityGroups[sig]]
                    else:
                        params['SecurityGroup.%d' %
                               (sig + 1, )] = securityGroups[sig]

        if 'blockDeviceMapping' in kwargs:
            if kwargs['blockDeviceMapping'] is not None:
                if not isinstance(kwargs['blockDeviceMapping'], list):
                    kwargs['blockDeviceMapping'] = [
                        kwargs['blockDeviceMapping']
                    ]
                for sig, blockDevice in enumerate(
                        kwargs['blockDeviceMapping']):
                    params['BlockDeviceMapping.%d.DeviceName' %
                           (sig + 1, )] = blockDevice["DeviceName"]
                    params['BlockDeviceMapping.%d.VirtualName' %
                           (sig + 1, )] = blockDevice["VirtualName"]

        if 'location' in kwargs:
            availability_zone = kwargs['location']
            if availability_zone:
                #if availability_zone != self.region_name:
                #    raise IaasException('Invalid availability zone: %s' % availability_zone)
                params['Placement.AvailabilityZone'] = availability_zone

        if 'kernelId' in kwargs and kwargs[
                'kernelId'] is not None and '' != kwargs['kernelId']:
            params['KernelId'] = kwargs['kernelId']

        if 'ramdiskId' in kwargs and kwargs[
                'ramdiskId'] is not None and '' != kwargs['ramdiskId']:
            params['RamdiskId'] = kwargs['ramdiskId']

        if 'keyName' in kwargs and kwargs[
                'keyName'] is not None and '' != kwargs['keyName']:
            params['KeyName'] = kwargs['keyName']

        if isPrivateIp and 'privateIpAddress' in kwargs and kwargs[
                'privateIpAddress'] is not None and '' != kwargs[
                    'privateIpAddress']:
            params['PrivateIpAddress'] = kwargs['privateIpAddress']

        if 'userData' in kwargs and kwargs['userData'] is not None:
            params['UserData'] = base64.b64encode(kwargs['userData'])

        if 'ex_clienttoken' in kwargs and kwargs['ex_clienttoken'] is not None:
            params['ClientToken'] = kwargs['ex_clienttoken']

        instance = None
        try:
            self.logger.info(params)
            object = self.connection.request(self.path, params=params).object
            nodes = self._to_nodes(object, 'instancesSet/item')
            instance = nodes[0]

        except Exception:
            self.logger.error(traceback.format_exc())
            #インスタンスが存在しない場合
            raise IaasException("EPROCESS-000105", [])

        #実行ログ
        self.logger.info(None, "IPROCESS-100115", [instance.id])

        return instance

    #LibCloudで提供されていない為独自実装
    def startInstance(self, instanceid):
        params = {'Action': 'StartInstances', 'InstanceId.0': instanceid}
        try:
            elem = self.connection.request(self.path, params=params).object
            previousStates = []
            for rs in findall(element=elem,
                              xpath='instancesSet/item',
                              namespace=NAMESPACE):
                code = findtext(element=rs,
                                xpath='previousState/code',
                                namespace=NAMESPACE)
                name = findtext(element=rs,
                                xpath='previousState/name',
                                namespace=NAMESPACE)
                previousStates.append({"code": code, "name": name})

            if len(previousStates) > 1:
                raise IaasException("EPROCESS-000127", [
                    instanceid,
                ])

            #実行ログ
            self.logger.info(None, "IPROCESS-100111", [
                instanceid,
            ])

            return previousStates[0]

        except Exception:
            # インスタンス起動失敗時
            raise IaasException("EPROCESS-000125", [
                instanceid,
            ])
        return None

    #LibCloudで提供されていない為独自実装
    def stopInstance(self, instanceid):
        params = {'Action': 'StopInstances', 'InstanceId.0': instanceid}
        try:
            elem = self.connection.request(self.path, params=params).object
            previousStates = []
            for rs in findall(element=elem,
                              xpath='instancesSet/item',
                              namespace=NAMESPACE):
                code = findtext(element=rs,
                                xpath='previousState/code',
                                namespace=NAMESPACE)
                name = findtext(element=rs,
                                xpath='previousState/name',
                                namespace=NAMESPACE)
                previousStates.append({"code": code, "name": name})

            if len(previousStates) > 1:
                raise IaasException("EPROCESS-000130", [
                    instanceid,
                ])

            #実行ログ
            self.logger.info(None, "IPROCESS-100113", [
                instanceid,
            ])

            return previousStates[0]
        except Exception:
            # インスタンス停止失敗時
            raise IaasException("EPROCESS-000128", [
                instanceid,
            ])
        return None

    #本来destroy_nodeはnode自体を受け取るがこの関数はIDを受ける形とした
    def terminateInstance(self, instanceid):
        params = {'Action': 'TerminateInstances', 'InstanceId': instanceid}
        try:
            elem = self.connection.request(self.path, params=params).object
            previousStates = []
            for rs in findall(element=elem,
                              xpath='instancesSet/item',
                              namespace=NAMESPACE):
                code = findtext(element=rs,
                                xpath='previousState/code',
                                namespace=NAMESPACE)
                name = findtext(element=rs,
                                xpath='previousState/name',
                                namespace=NAMESPACE)
                previousStates.append({"code": code, "name": name})

            if len(previousStates) > 1:
                #複数のインスタンスが削除された場合
                raise IaasException("EPROCESS-000108", [
                    instanceid,
                ])

            #実行ログ
            self.logger.info(None, "IPROCESS-100117", [
                instanceid,
            ])

            return previousStates[0]
        except Exception:
            # インスタンス削除失敗時
            raise IaasException("EPROCESS-000107", [
                instanceid,
            ])
        return None

    def modifyInstanceAttribute(self, instanceid, **kwargs):
        params = {
            'Action': 'ModifyInstanceAttribute',
            'InstanceId': instanceid
        }

        #現状はインスタンスタイプのみ変更に対応する
        if 'InstanceType' in kwargs and kwargs[
                'InstanceType'] is not None and '' != kwargs['InstanceType']:
            params['InstanceType.Value'] = kwargs['InstanceType']
        elif 'GroupId' in kwargs and kwargs[
                'GroupId'] is not None and '' != kwargs['GroupId']:
            params['GroupId'] = kwargs['GroupId']

        try:
            self.connection.request(self.path, params=params).object
        except Exception:
            # インスタンス変更失敗時
            raise IaasException("EPROCESS-000107", [
                instanceid,
            ])
        return None

    ############################################################
    #
    #    Volume 系
    #
    ############################################################

    #LibCloudで提供されていない為独自実装
    def createVolume(self, availabilityZone, size=None, snapshotId=None):
        params = {
            'Action': 'CreateVolume',
            'AvailabilityZone': availabilityZone
        }

        #任意
        if size != None:
            params.update({'Size': str(size)})
        if snapshotId != None:
            params.update({'SnapshotId': snapshotId})

        elem = self.connection.request(self.path, params=params).object
        voluem = self._to_volume(elem)

        #実行ログ
        self.logger.info(None, "IPROCESS-100121", [
            voluem.volumeId,
        ])

        return voluem

    #LibCloudで提供されていない為独自実装
    def attachVolume(self, volumeId, instanceId, device):
        params = {
            'Action': 'AttachVolume',
            'VolumeId': volumeId,
            'InstanceId': instanceId,
            'Device': device
        }
        elem = self.connection.request(self.path, params=params).object

        #実行ログ
        self.logger.info(None, "IPROCESS-100123", [volumeId, instanceId])

        return self._to_attachmentSet(elem)

    #LibCloudで提供されていない為独自実装
    def detachVolume(self, volumeId, instanceId=None, device=None):
        params = {'Action': 'DetachVolume', 'VolumeId': volumeId}

        #任意パラメータ
        if instanceId != None:
            params.update({'InstanceId': instanceId})
        if device != None:
            params.update({'Device': device})

        elem = self.connection.request(self.path, params=params).object
        #実行ログ
        self.logger.info(None, "IPROCESS-100125", [volumeId, instanceId])

        #deleteOnTerminationが戻りのエレメントに無いのでそのまま動くか不明
        return self._to_attachmentSet(elem)

    #LibCloudで提供されていない為独自実装
    def deleteVolume(self, volumeId):
        params = {'Action': 'DeleteVolume', 'VolumeId': volumeId}

        self.connection.request(self.path, params=params).object

        #実行ログ
        self.logger.info(None, "IPROCESS-100127", [
            volumeId,
        ])

    ############################################################
    #
    #    Address 系
    #
    ############################################################

    #LibCloudで提供されていない為独自実装
    #Domainを指定することも可能だが無視する
    def allocateAddress(self):
        params = {'Action': 'AllocateAddress'}

        elem = self.connection.request(self.path, params=params).object

        publicIp = findattr(element=elem,
                            xpath="publicIp",
                            namespace=NAMESPACE)

        # ログ出力
        self.logger.info(None, "IPROCESS-100133", [
            publicIp,
        ])

        return publicIp

    #LibCloudで提供されていない為独自実装
    def allocateVpcAddress(self):
        params = {'Action': 'AllocateAddress', 'Domain': 'vpc'}

        elem = self.connection.request(self.path, params=params).object

        publicIp = findattr(element=elem,
                            xpath="publicIp",
                            namespace=NAMESPACE)

        # ログ出力
        self.logger.info(None, "IPROCESS-100133", [
            publicIp,
        ])

        return publicIp

    #LibCloudで提供されていない為独自実装
    def associateAddress(self, publicIp, instanceId):
        params = {
            'Action': 'AssociateAddress',
            'PublicIp': publicIp,
            'InstanceId': instanceId
        }

        self.connection.request(self.path, params=params).object
        # ログ出力
        self.logger.info(None, "IPROCESS-100131", [
            publicIp,
            instanceId,
        ])

    #LibCloudで提供されていない為独自実装
    def associateVpcAddress(self, publicIp, instanceId, allocationId):
        params = {
            'Action': 'AssociateAddress',
            'InstanceId': instanceId,
            'AllocationId': allocationId
        }

        self.connection.request(self.path, params=params).object
        # ログ出力
        self.logger.info(None, "IPROCESS-100131", [
            publicIp,
            instanceId,
            allocationId,
        ])

    #LibCloudで提供されていない為独自実装
    def disassociateAddress(self, publicIp, instanceId):
        params = {'Action': 'DisassociateAddress', 'PublicIp': publicIp}

        self.connection.request(self.path, params=params).object

        # ログ出力
        self.logger.info(None, "IPROCESS-100132", [
            publicIp,
            instanceId,
        ])

    #LibCloudで提供されていない為独自実装
    def disassociateVpcAddress(self, publicIp, instanceId, associationId):
        params = {
            'Action': 'DisassociateAddress',
            'AssociationId': associationId
        }

        self.connection.request(self.path, params=params).object

        # ログ出力
        self.logger.info(None, "IPROCESS-100132", [
            publicIp,
            instanceId,
            associationId,
        ])

    #LibCloudで提供されていない為独自実装
    def releaseAddress(self, publicIp):
        params = {'Action': 'ReleaseAddress', 'PublicIp': publicIp}

        self.connection.request(self.path, params=params).object
        # ログ出力
        self.logger.info(None, "IPROCESS-100134", [
            publicIp,
        ])

    #LibCloudで提供されていない為独自実装
    def releaseVpcAddress(self, publicIp, allocationId):
        params = {'Action': 'ReleaseAddress', 'AllocationId': allocationId}

        self.connection.request(self.path, params=params).object
        # ログ出力
        self.logger.info(None, "IPROCESS-100134", [
            publicIp,
            allocationId,
        ])

    ############################################################
    #
    #    KeyPair 系
    #
    ############################################################

    #LibCloudで提供されてるex_create_keypairはKeyNameを戻り値に含まない為、独自実装
    def createKeyPair(self, keyName):
        params = {'Action': 'CreateKeyPair', 'KeyName': keyName}

        elem = self.connection.request(self.path, params=params).object

        keypair = self._to_keypair(elem)
        keypair.setKeyMaterial(
            findattr(element=elem, xpath="keyMaterial", namespace=NAMESPACE))

    #LibCloudで提供されていない為独自実装
    def deleteKeyPair(self, keyName):
        params = {'Action': 'DeleteKeyPair', 'KeyName': keyName}

        self.connection.request(self.path, params=params).object

        #戻り値なし

    #LibCloudで提供されてるex_import_keypairはファイルベースの為、独自実装
    def importKeyPair(self, keyName, publicKeyMaterial):
        publicKeyMaterial = base64.b64encode(publicKeyMaterial)
        params = {
            'Action': 'ImportKeyPair',
            'KeyName': keyName,
            'PublicKeyMaterial': publicKeyMaterial
        }

        elem = self.connection.request(self.path, params=params).object

        return self._to_keypair(elem)

    ############################################################
    #
    #    Snapshot 系
    #
    ############################################################

    def createSnapshot(self, volumeId, description=None):
        #Owner, RestorableBy, Filter(name/Value)で絞る事ができるが制限する
        params = {'Action': 'CreateSnapshot', 'VolumeId': volumeId}
        #任意パラメータ
        if description != None:
            params.update({'Description': description})

        elem = self.connection.request(self.path, params=params).object
        snapshot = self._to_snapshot(elem)

        # ログ出力
        self.logger.info(None, "IPROCESS-100151",
                         [snapshot.snapshotId, volumeId])

        return snapshot

    def deleteSnapshot(self, snapshotId):
        params = {'Action': 'DeleteSnapshot', 'SnapshotId': snapshotId}

        self.connection.request(self.path, params=params).object
        # ログ出力
        self.logger.info(None, "IPROCESS-100153", [snapshotId])

    ############################################################
    #
    #    Tags 系
    #
    ############################################################

    def createTags(self, resourceId, tagSets):
        if not tagSets:
            return

        params = {'Action': 'CreateTags', 'ResourceId.0': resourceId}
        i = 0
        for tag in tagSets:
            params['Tag.%d.Key' % i] = tag.key
            params['Tag.%d.Value' % i] = tag.value
            i = i + 1
            # ログ出力
            self.logger.info(None, "IPROCESS-100154",
                             [resourceId, tag.key, tag.value])

        self.connection.request(self.path, params=params).object

    def createTag(self, instanceId, tag):
        if not tag:
            return
        tags = [tag]
        self.createTags(instanceId, tags)

    def deleteTags(self, instanceId, tagSets):
        if not tagSets:
            return

        params = {'Action': 'DeleteTags', 'ResourceId.0': instanceId}
        i = 0
        for tag in tagSets:
            params['Tag.%d.Key' % i] = tag.key
            params['Tag.%d.Value' % i] = tag.value
            i = i + 1

        self.connection.request(self.path, params=params).object

    ############################################################
    #
    #    その他
    #
    ############################################################
    def getPasswordData(self, InstanceId):
        params = {'Action': 'GetPasswordData', 'InstanceId': InstanceId}

        elem = self.connection.request(self.path, params=params).object

        #True Falseを受ける
        passwdData = findattr(element=elem,
                              xpath="passwordData",
                              namespace=NAMESPACE)

        if isEmpty(passwdData):
            # パスワードデータを取得できない場合
            raise IaasException("EPROCESS-000133", [
                InstanceId,
            ])
        return passwdData

    '''********************************以下ローカルメソッド******************************************
    '''

    def build_list_params(self, params, items, label):
        if isinstance(items, str):
            items = [items]
        for i, item in enumerate(items, 1):
            params[label % i] = item

    def _to_image(self, element):
        n = NodeImage(id=findtext(element=element,
                                  xpath='imageId',
                                  namespace=NAMESPACE),
                      name=findtext(element=element,
                                    xpath='imageLocation',
                                    namespace=NAMESPACE),
                      driver=self.connection.driver,
                      extra={
                          'rootDeviceType':
                          findattr(element=element,
                                   xpath="rootDeviceType",
                                   namespace=NAMESPACE),
                          'platform':
                          findattr(element=element,
                                   xpath="platform",
                                   namespace=NAMESPACE),
                      })
        return n

    def _to_tagSet(self, element):
        n = TagSet(
            resourceId=findattr(element=element,
                                xpath="resourceId",
                                namespace=NAMESPACE),
            resourceType=findattr(element=element,
                                  xpath="resourceType",
                                  namespace=NAMESPACE),
            key=findattr(element=element, xpath="key", namespace=NAMESPACE),
            value=findattr(element=element, xpath="value",
                           namespace=NAMESPACE),
        )
        return n

    def _to_subnetInfo(self, element):
        n = SubnetInfo(
            subnetId=findattr(element=element,
                              xpath="subnetId",
                              namespace=NAMESPACE),
            state=findattr(element=element, xpath="state",
                           namespace=NAMESPACE),
            vpcId=findattr(element=element, xpath="vpcId",
                           namespace=NAMESPACE),
            cidrBlock=findattr(element=element,
                               xpath="cidrBlock",
                               namespace=NAMESPACE),
            availableIpAddressCount=findattr(element=element,
                                             xpath="availableIpAddressCount",
                                             namespace=NAMESPACE),
            availabilityZone=findattr(element=element,
                                      xpath="availabilityZone",
                                      namespace=NAMESPACE),
            tagSet=findattr(element=element,
                            xpath="tagSet",
                            namespace=NAMESPACE),
        )
        return n

    def _to_vpcInfo(self, element):
        n = VpcInfo(
            vpcId=findattr(element=element, xpath="vpcId",
                           namespace=NAMESPACE),
            state=findattr(element=element, xpath="state",
                           namespace=NAMESPACE),
            cidrBlock=findattr(element=element,
                               xpath="cidrBlock",
                               namespace=NAMESPACE),
            dhcpOptionsId=findattr(element=element,
                                   xpath="dhcpOptionsId",
                                   namespace=NAMESPACE),
            tagSet=findattr(element=element,
                            xpath="tagSet",
                            namespace=NAMESPACE),
        )
        return n

    def _to_regionInfo(self, element):
        n = RegionInfo(
            regionName=findattr(element=element,
                                xpath="regionName",
                                namespace=NAMESPACE),
            regionEndpoint=findattr(element=element,
                                    xpath="regionEndpoint",
                                    namespace=NAMESPACE),
        )
        return n

    def _to_snapshot(self, element):
        n = SnapshotSet(
            snapshotId=findattr(element=element,
                                xpath="snapshotId",
                                namespace=NAMESPACE),
            volumeId=findattr(element=element,
                              xpath="volumeId",
                              namespace=NAMESPACE),
            status=findattr(element=element,
                            xpath="status",
                            namespace=NAMESPACE),
            startTime=findattr(element=element,
                               xpath="startTime",
                               namespace=NAMESPACE),
            progress=findattr(element=element,
                              xpath="progress",
                              namespace=NAMESPACE),
            ownerId=findattr(element=element,
                             xpath="ownerId",
                             namespace=NAMESPACE),
            volumeSize=findattr(element=element,
                                xpath="volumeSize",
                                namespace=NAMESPACE),
            description=findattr(element=element,
                                 xpath="description",
                                 namespace=NAMESPACE),
            tagSet=findattr(element=element,
                            xpath="tagSet",
                            namespace=NAMESPACE),
        )
        return n

    def _to_securityGroup(self, element):

        ipPermissions = []
        for rs in findall(element=element,
                          xpath='ipPermissions/item',
                          namespace=NAMESPACE):
            ipPermissions.append(self._to_ipPermissions(rs))

        n = SecurityGroup(
            ownerId=findattr(element=element,
                             xpath="ownerId",
                             namespace=NAMESPACE),
            groupId=findattr(element=element,
                             xpath="groupId",
                             namespace=NAMESPACE),
            groupName=findattr(element=element,
                               xpath="groupName",
                               namespace=NAMESPACE),
            groupDescription=findattr(element=element,
                                      xpath="groupDescription",
                                      namespace=NAMESPACE),
            vpcId=findattr(element=element, xpath="vpcId",
                           namespace=NAMESPACE),
            ipPermissions=ipPermissions,
            ipPermissionsEgress=findattr(element=element,
                                         xpath="ipPermissionsEgress",
                                         namespace=NAMESPACE),
            tagSet=findattr(element=element,
                            xpath="tagSet",
                            namespace=NAMESPACE),
        )
        return n

    def _to_ipPermissions(self, element):
        ipRanges = []
        for rs in findall(element=element,
                          xpath='ipRanges/item',
                          namespace=NAMESPACE):
            ipRanges.append(
                findattr(element=rs, xpath="cidrIp", namespace=NAMESPACE))

        n = IpPermissions(
            ipProtocol=findattr(element=element,
                                xpath="ipProtocol",
                                namespace=NAMESPACE),
            fromPort=findattr(element=element,
                              xpath="fromPort",
                              namespace=NAMESPACE),
            toPort=findattr(element=element,
                            xpath="toPort",
                            namespace=NAMESPACE),
            groups=findattr(element=element,
                            xpath="groups",
                            namespace=NAMESPACE),
            ipRanges=ipRanges,
        )
        return n

    def _to_volumes(self, element):
        #ステータスチェック(保留)
        #try:
        #    state = self.NODE_STATE_MAP[
        #            findattr(element=element, xpath="instanceState/name",
        #                     namespace=NAMESPACE)
        #    ]
        #except KeyError:
        #    state = NodeState.UNKNOWN

        tags = dict(
            (findtext(element=item, xpath='key', namespace=NAMESPACE),
             findtext(element=item, xpath='value', namespace=NAMESPACE))
            for item in findall(
                element=element, xpath='tagSet/item', namespace=NAMESPACE))

        attachment = []
        for rs in findall(element=element,
                          xpath='attachmentSet/item',
                          namespace=NAMESPACE):
            attachmentset = self._to_attachmentSet(rs)
            attachmentset.setDeleteOnTermination(
                findattr(element=element,
                         xpath="deleteOnTermination",
                         namespace=NAMESPACE))
            attachment.append(attachmentset)

        v = self._to_volume(element, attachment, tags)
        return v

    def _to_volume(self, element, attachmentSet=None, tags=None):
        v = Volume(volumeId=findattr(element=element,
                                     xpath="volumeId",
                                     namespace=NAMESPACE),
                   size=findattr(element=element,
                                 xpath="size",
                                 namespace=NAMESPACE),
                   snapshotId=findattr(element=element,
                                       xpath="snapshotId",
                                       namespace=NAMESPACE),
                   availabilityZone=findattr(element=element,
                                             xpath="availabilityZone",
                                             namespace=NAMESPACE),
                   status=findattr(element=element,
                                   xpath="status",
                                   namespace=NAMESPACE),
                   createTime=findattr(element=element,
                                       xpath="createTime",
                                       namespace=NAMESPACE),
                   attachmentSet=attachmentSet,
                   tagSet=tags)
        return v

    def _to_attachmentSet(self, element):
        n = AttachmentSet(
            volumeId=findattr(element=element,
                              xpath="volumeId",
                              namespace=NAMESPACE),
            instanceId=findattr(element=element,
                                xpath="instanceId",
                                namespace=NAMESPACE),
            device=findattr(element=element,
                            xpath="device",
                            namespace=NAMESPACE),
            status=findattr(element=element,
                            xpath="status",
                            namespace=NAMESPACE),
            attachTime=findattr(element=element,
                                xpath="attachTime",
                                namespace=NAMESPACE),
        )
        return n

    def _to_address(self, element):
        n = Address(
            publicIp=findattr(element=element,
                              xpath="publicIp",
                              namespace=NAMESPACE),
            domain=findattr(element=element,
                            xpath="domain",
                            namespace=NAMESPACE),
            instanceId=findattr(element=element,
                                xpath="instanceId",
                                namespace=NAMESPACE),
            allocationId=findattr(element=element,
                                  xpath="allocationId",
                                  namespace=NAMESPACE),
            associationId=findattr(element=element,
                                   xpath="associationId",
                                   namespace=NAMESPACE),
        )
        return n

    def _to_keypair(self, element):
        n = KeyPair(
            keyName=findattr(element=element,
                             xpath="keyName",
                             namespace=NAMESPACE),
            keyFingerprint=findattr(element=element,
                                    xpath="keyFingerprint",
                                    namespace=NAMESPACE),
            #keyMaterial = findattr(element=element, xpath="keyMaterial", namespace=NAMESPACE),
        )
        return n
Ejemplo n.º 27
0
class VCloudController(IaasController):

    logger = IaasLogger()

    conn = None
    client = None
    accessInfo = None

    instancecontroller = None
    volumecontroller = None
    addresscontroller = None
    loadBalancercontroller = None
    othercontroller = None

    def __init__(self, conn, accessInfo, platforminfo):
        self.conn = conn
        self.accessInfo = accessInfo
        self.client = VCloudIaasClient(platforminfo, accessInfo["USER_NAME"], accessInfo["ACCESS_ID"], accessInfo["SECRET_KEY"])

        #コントローラ作成
        self.othercontroller         = VCloudOtherController(platforminfo, self.client, self.conn)
        self.instancecontroller      = VCloudInstanceController(platforminfo, self.client, self.conn)
        self.volumecontroller        = VCloudVolumController(platforminfo, self.client, self.conn)


    def __del__(self):
        #保険
        self.conn.rollback()

        #エラー時に残るタスク登録を消す
        taskTable = self.conn.getTable("VCLOUD_TASK")
        sql = taskTable.delete().where(taskTable.c.P_ID == os.getpid())
        self.conn.execute(sql)
        self.conn.commit()
        #セッションクローズ
        self.conn.close()

    def doWaitingExecution(self, farm_name):
        vdc = self.client.getUseVdc()
        vappname = vdc.name + "-" + farm_name
        #タスク情報を登録し1度コミット
        taskTable = self.conn.getTable("VCLOUD_TASK")
        sql = taskTable.insert({"ADDRESS_NO":None,
                            "P_ID":os.getpid(),
                            "REGIST_TIME":datetime.datetime.today(),
                            "VAPP":vappname})
        self.conn.execute(sql)
        self.conn.commit()

        #同タイム対策スリープ
        time.sleep(3)

        #自分のPIDの順番まで待つ
        status = "stop"
        prePid = "0"
        roopCount = 0
        while status != 'go':
            #登録時間の早いタスクを取得(常に最新のDB状況を参照する)
            self.conn.remakeSession()
            task = self.conn.selectOne(taskTable.select()
                                       .where(taskTable.c.VAPP == vappname)
                                       .order_by(taskTable.c.REGIST_TIME, taskTable.c.P_ID))
            self.logger.info(os.getpid())
            self.logger.info(task)
            if os.getpid() == task["P_ID"]:
                vapp = self.client.describeMyCloud(vdc, farm_name)
                #VAPPが実行中タスクを持っている場合は待つ
                if vapp.extra["task"]:
                    roopCount = roopCount +1
                    time.sleep(10)
                else:
                    status = 'go'
            else:
                #前回PIDが同じ場合ループカウントを増やす
                if prePid == task["P_ID"]:
                    roopCount = roopCount +1
                else:
                    #新しいPIDの場合は0に戻す
                    roopCount = 0
                    prePid = task["P_ID"]
                time.sleep(10)

            #タイムアウト
            if roopCount > 100:
                raise IaasException("EPROCESS-000812", [os.getpid(),])

    def doWaitingExecutionEnd(self):
        taskTable = self.conn.getTable("VCLOUD_TASK")
        sql = taskTable.delete().where(taskTable.c.P_ID == os.getpid())
        self.conn.execute(sql)


    def getVappName(self, farmNo=None, instanceNo=None, vm_name=None):

        farmNo = farmNo
        instanceNo = instanceNo
        vm_name = vm_name

        if vm_name is not None:
            #vCloud_INSTANCE 取得
            tableVCINS = self.conn.getTable("VCLOUD_INSTANCE")
            vcInstance = self.conn.selectOne(tableVCINS.select(tableVCINS.c.VM_NAME==vm_name))
            instanceNo = vcInstance["INSTANCE_NO"]

        if instanceNo is not None:
            #PCC_INSTANCE 取得
            tableINS = self.conn.getTable("INSTANCE")
            pccInstance = self.conn.selectOne(tableINS.select(tableINS.c.INSTANCE_NO==instanceNo))
            farmNo = pccInstance["FARM_NO"]

        if farmNo is not None:
            #FARM 取得
            tableFarm = self.conn.getTable("FARM")
            farm = self.conn.selectOne(tableFarm.select(tableFarm.c.FARM_NO==farmNo))
            return farm["FARM_NAME"]

        else:
            return None

    def synchronizeCloud(self, platformNo):
        self.othercontroller.synchronizeCloud(platformNo)
        self.conn.commit()
        return True

    def describeNetwork(self):
        networks = self.client.describeVdcNetwork()
        rtString = ''
        for network in networks:
            if rtString != '':
                rtString = rtString + "##"

            name = network.name
            value = "GATEWAY="+str(network.gateway)
            value = value + ",NETMASK=" + str(network.netmask)
            value = value + ",DNS1=" + str(network.dns1)
            value = value + ",DNS2=" + str(network.dns2)
            value = value + ",RANGEF=" + str(network.rangeF)
            value = value + ",RANGET=" + str(network.rangeT)
            value = value + ",PRIMARY=" + str(network.primary)

            #とりあえず必要な情報のみ返します
            rtString = rtString + name + '#' + value

        self.conn.commit()
        return "RESULT:" + rtString

    def createMyCloud(self, platformNo, farmName):

        self.othercontroller.createMyCloud(platformNo, farmName)
        self.conn.commit()
        return True

    def terminateMyCloud(self, platformNo, farmNo):
        #VAPPロック
        self.doWaitingExecution(self.getVappName(farmNo=farmNo))

        self.othercontroller.terminateMyCloud(platformNo, farmNo)

        #VAPPロック解除
        self.doWaitingExecutionEnd()
        self.conn.commit()
        return True


    def startInstance(self, instanceNo):
        #VAPPロック
        self.doWaitingExecution(self.getVappName(instanceNo=instanceNo))

        #仮想マシンを(作成)起動
        self.instancecontroller.startInstance(instanceNo)

        # ボリュームに関する処理
        table = self.conn.getTable("VCLOUD_DISK")
        volumes = self.conn.select(table.select(table.c.INSTANCE_NO==instanceNo))
        for disk in volumes:
            if isNotEmpty(disk["COMPONENT_NO"]):
                # コンポーネント番号がある場合はスキップ
                continue

            if isNotEmpty(disk["DISK_ID"]):
                # アタッチされている場合はスキップ
                continue

            #Volumeスタート
            self.volumecontroller.startVolume(instanceNo, disk["DISK_NO"])

        #VAPPロック解除
        self.doWaitingExecutionEnd()
        self.conn.commit()
        return True


    def stopInstance(self, instanceNo):
        #VAPPロック
        self.doWaitingExecution(self.getVappName(instanceNo=instanceNo))

        #仮想マシンを停止
        self.instancecontroller.stopInstance(instanceNo)

        # ボリュームに関する処理
        tableDsk = self.conn.getTable("VCLOUD_DISK")
        volumes = self.conn.select(tableDsk.select(tableDsk.c.INSTANCE_NO==instanceNo))
        for disk in volumes:
            #アンデタッチの場合抜ける
            if getTrueFalseProperty("unDetachVolume"):
                break

            # filestorage は外さない
            if isBit(disk["DATA_DISK"]):
                continue

            #Volumのストップ
            self.volumecontroller.stopVolume(instanceNo, disk["DISK_NO"])

        #VAPPロック解除
        self.doWaitingExecutionEnd()
        self.conn.commit()
        return True


    def terminateInstance(self, vm_name):
        #vCloud_INSTANCE 取得
        tableVCINS = self.conn.getTable("VCLOUD_INSTANCE")
        vcInstance = self.conn.selectOne(tableVCINS.select(tableVCINS.c.VM_NAME==vm_name))
        if vcInstance is None:
            #1度も起動されて無い場合はそのまま返す
            return

        #VAPPロック
        self.doWaitingExecution(self.getVappName(vm_name=vm_name))

        #仮想マシンを削除
        self.instancecontroller.terminate(vm_name)

        #VAPPロック解除
        self.doWaitingExecutionEnd()
        self.conn.commit()
        return True

    def startVolume(self, instanceNo, volumeNo):
        #VAPPロック
        self.doWaitingExecution(self.getVappName(instanceNo=instanceNo))

        self.volumecontroller.startVolume(instanceNo, volumeNo)
        #VAPPロック解除
        self.doWaitingExecutionEnd()
        self.conn.commit()
        return True

    def stopVolume(self, instanceNo, volumeNo):
        #VAPPロック
        self.doWaitingExecution(self.getVappName(instanceNo=instanceNo))

        self.volumecontroller.stopVolume(instanceNo, volumeNo)
        #VAPPロック解除
        self.doWaitingExecutionEnd()
        self.conn.commit()
        return True

    def deleteVolume(self, disk_no):

        tableVCDISK = self.conn.getTable("VCLOUD_DISK")
        vcdisk = self.conn.selectOne(tableVCDISK.select(tableVCDISK.c.DISK_NO==disk_no))
        #VCLOUD_INSTANCE 取得
        tableVCINS = self.conn.getTable("VCLOUD_INSTANCE")
        vcInstance = self.conn.selectOne(tableVCINS.select(tableVCINS.c.INSTANCE_NO==vcdisk["INSTANCE_NO"]))
        #FARM 取得
        tableFarm = self.conn.getTable("FARM")
        farm = self.conn.selectOne(tableFarm.select(tableFarm.c.FARM_NO==vcdisk["FARM_NO"]))

        #VAPPロック
        self.doWaitingExecution(farm["FARM_NAME"])

        #組織
        vdc = self.client.getUseVdc()
        #マイクラウド
        vApp = self.client.describeMyCloud(vdc, farm["FARM_NAME"])
        #既存VM検索
        vm = self.client.describeInstance(vApp, vcInstance["VM_NAME"])

        self.client.detachVolume(vm, vcdisk["DISK_ID"])

        #VAPPロック解除
        self.doWaitingExecutionEnd()
        self.conn.commit()
        return True

    def startLoadBalancer(self, loadBalancerNo):
        pass

    def stopLoadBalancer(self, loadBalancerNo):
        pass

    def configureLoadBalancer(self, loadBalancerNo):
        pass


    #TODO  後々はゾーンを取得するようにしなければいけない
    def allocateAddress(self, farmNo):
        pass

    def releaseAddress(self, addressNo, farmNo):
        pass

    def createSnapshot(self, volumeNo):
        pass

    def deleteSnapshot(self, snapshotNo):
        pass

    def getPasswordData(self, instanceNo):
        pass

    def describeKeyPairs(self):
        pass

    def createKeyPair(self, keyName):
        pass

    def deleteKeyPair(self, keyName):
        pass

    def importKeyPair(self, keyName, publicKeyMaterial):
        pass

    def describeSecurityGroups(self, vpcid = None):
        pass

    def describeAvailabilityZones(self):
        pass
class CloudStackController(IaasController):

    logger = IaasLogger()

    conn = None
    client = None
    accessInfo = None

    instancecontroller = None
    volumecontroller = None
    addresscontroller = None
    loadBalancercontroller = None
    othercontroller = None

    def __init__(self, conn, accessInfo, platforminfo):
        self.conn = conn
        self.accessInfo = accessInfo

        self.client = CloudStackIaasClient(platforminfo, accessInfo["USER_NAME"], accessInfo["ACCESS_ID"], accessInfo["SECRET_KEY"])
        #コントローラ作成
        self.instancecontroller      = CloudStackInstanceController(platforminfo, self.client, self.conn)
        self.volumecontroller        = CloudStackVolumController(platforminfo, self.client, self.conn)
        self.addresscontroller       = CloudStackAddressController(platforminfo, self.client, self.conn)
        self.loadBalancercontroller  = CloudStackLoadBalancercontroller(platforminfo, self.client, self.conn)
        self.othercontroller         = CloudStackOtherController(platforminfo, self.client, self.conn)

    def __del__(self):
        self.conn.rollback()
        self.conn.close()

    def describeDiskOfferings(self):
        return self.client.describeDiskOfferings()

    def describePublicIpAddresses(self, id):
        return self.client.describePublicIpAddresses(id)

    def describeOnlyInstances(self):
        return self.client.describeOnlyInstances()

    def describeServiceOfferings(self):
        return self.client.describeServiceOfferings()


    def describeImages(self):
        return self.client.describeImages()

    def describeInstances(self):
        return self.client.describeInstances()


    def startInstance(self, instanceNo):

        # インスタンスに関する処理   TODO タイムアウトリトライは未実装
        try:
            self.instancecontroller.startInstance(instanceNo)
        except Exception, e:
            self.logger.error(traceback.format_exc())
            raise

        # ボリュームに関する処理
        table = self.conn.getTable("CLOUDSTACK_VOLUME")
        volumes = self.conn.select(table.select(table.c.INSTANCE_NO==instanceNo))
        for volume in volumes:
            if isNotEmpty(volume["COMPONENT_NO"]):
                # コンポーネント番号がある場合はスキップ
                continue
            #Volumeスタート
            self.volumecontroller.startVolume(instanceNo, volume["VOLUME_NO"])

        # アドレスに関する処理
        self.addresscontroller.startAddress(instanceNo)

        self.conn.commit()
        return True
Ejemplo n.º 29
0
class ec2InstanceController(object):

    logger = IaasLogger()

    ERROR_RETRY_COUNT = 3

    client = None
    conn = None
    platforminfo = None

    def __init__(self, platforminfo, ec2iaasclient, conn):
        self.client = ec2iaasclient
        self.conn = conn
        self.platforminfo = platforminfo

    def startInstance(self, instanceNo):
        #AWS_INSTANCE 取得
        tableAWSINS = self.conn.getTable("AWS_INSTANCE")
        awsInstance = self.conn.selectOne(
            tableAWSINS.select(tableAWSINS.c.INSTANCE_NO == instanceNo))

        #PCC_INSTANCE 取得
        tableINS = self.conn.getTable("INSTANCE")
        pccInstance = self.conn.selectOne(
            tableINS.select(tableINS.c.INSTANCE_NO == instanceNo))

        #イメージの取得  再考の余地あり
        image = getImage(pccInstance["IMAGE_NO"])

        # インスタンスイメージの場合や、EBSイメージでインスタンスIDがない場合
        if (image["ebsImage"] == "false"
                or isEmpty(awsInstance["INSTANCE_ID"])):

            #インスタンスIDがある場合はスキップ
            if (isEmpty(awsInstance["INSTANCE_ID"]) == False):
                return

            #インスタンスの作成
            self.run(instanceNo, awsInstance, pccInstance, image)

            #インスタンスの作成待ち
            self.waitRun(instanceNo, pccInstance)

            #インスタンスにタグをつける
            self.createTag(instanceNo, pccInstance)

            #winodowsなら
            if (startsWithIgnoreCase(image["os"], "windows")):
                self.waitGetPasswordData(instanceNo, awsInstance)

        # EBSイメージでインスタンスIDがある場合
        else:
            # インスタンスが停止中でない場合はスキップ
            if (awsInstance["STATUS"] != "stopped"):
                return
            # インスタンスの起動
            self.start(instanceNo, awsInstance, pccInstance)

            # インスタンスの起動待ち
            self.waitStart(instanceNo, pccInstance)

    def stopInstance(self, instanceNo):
        #AWS_INSTANCE 取得
        tableAWSINS = self.conn.getTable("AWS_INSTANCE")
        awsInstance = self.conn.selectOne(
            tableAWSINS.select(tableAWSINS.c.INSTANCE_NO == instanceNo))

        # インスタンスIDがない場合はスキップ
        if (isEmpty(awsInstance["INSTANCE_ID"])):
            return

        #PCC_INSTANCE 取得
        tableINS = self.conn.getTable("INSTANCE")
        pccInstance = self.conn.selectOne(
            tableINS.select(tableINS.c.INSTANCE_NO == instanceNo))

        #イメージの取得  再考の余地あり
        image = getImage(pccInstance["IMAGE_NO"])

        # インスタンスイメージの場合
        if image["ebsImage"] == "false":
            try:
                # インスタンスの削除
                self.terminate(instanceNo, awsInstance, pccInstance)

                # インスタンスの削除待ち
                self.waitTerminate(instanceNo, pccInstance)

            except Exception, e:
                self.logger.error(traceback.format_exc())
                # 情報が不整合(インスタンス異常終了時など)の場合、警告ログと後始末のみ行う
                self.logger.warn(e.massage)

                updateDict = self.conn.selectOne(
                    tableAWSINS.select(
                        tableAWSINS.c.INSTANCE_NO == instanceNo))
                updateDict["INSTANCE_ID"] = None
                updateDict["STATUS"] = None
                updateDict["DNS_NAME"] = None
                updateDict["PRIVATE_DNS_NAME"] = None
                updateDict["IP_ADDRESS"] = None
                updateDict["PRIVATE_IP_ADDRESS"] = None
                sql = tableAWSINS.update(
                    tableAWSINS.c.INSTANCE_NO == updateDict["INSTANCE_NO"],
                    values=updateDict)
                self.conn.execute(sql)

        # EBSイメージの場合
        else:
Ejemplo n.º 30
0
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 # GNU General Public License for more details.
 # 
 # You should have received a copy of the GNU General Public License
 # along with PrimeCloud Controller(TM). If not, see <http://www.gnu.org/licenses/>.
 # 
from iaasgw.log.log import IaasLogger
from iaasgw.utils.iaasSelecter import iaasSelect
import os
import sys
import traceback


if __name__ == '__main__':
    param = sys.argv
    logger = IaasLogger()

    #ログ用パラメータ
    logparam = ["StartVolume",os.getpid(), "インスタンスNo:%s, ボリュームNo:%s" %(str(param[3]),str(param[3]))]
    logger.start(logparam)

    #実行
    try:
        #パラメータ解説
        #  0.ファイル名
        #  1.ユーザー名
        #  2.プラットフォームNo
        #  3.インスタンスNo
        #  4.ボリュームNo
        #
        # 例:param = [None, "1", "6", "1", "7", "1"]
Ejemplo n.º 31
0
class azureOtherController(object):
    logger = IaasLogger()

    client = None
    conn = None
    platforminfo = None

    def __init__(self, platforminfo, azureiaasclient, conn):
        self.client = azureiaasclient
        self.conn = conn
        self.platforminfo = platforminfo

    def createCloudServiceFor(self, platformNo):
        platformTable = self.conn.getTable("PLATFORM_AZURE")
        platformInfo = self.conn.selectOne(platformTable.select\
            (platformTable.c.PLATFORM_NO==platformNo))

        # クラウドサービスの存在確認
        cloudService = platformInfo['CLOUD_SERVICE_NAME']
        status = self.client.getCloudServiceStatus(cloudService)
        self.logger.info('      Cloud Service: %s, Status: %s' %
                         (cloudService, status))

        # クラウドサービスが存在しない場合、作成する
        if status is None:
            affinityGroup = platformInfo['AFFINITY_GROUP_NAME']
            self.logger.debug('      Trying to create Cloud Service: %s' %
                              (cloudService))
            status = self.client.createCloudService(cloudService,
                                                    affinityGroup)
            self.logger.info('      Cloud Service: %s, Status: %s' %
                             (cloudService, status))
        else:
            # ステータスが作成完了以外の場合の処理は要検討
            pass

    def createStorageAccountFor(self, platformNo):
        platformTable = self.conn.getTable("PLATFORM_AZURE")
        platformInfo = self.conn.selectOne(platformTable.select\
            (platformTable.c.PLATFORM_NO==platformNo))

        # ストレージアカウントの存在確認
        # 名前が要件を満たしているか確認必要
        # Storage account names must be between 3 and 24 characters in length and use numbers and lower-case letters only.
        storageAccount = platformInfo['STORAGE_ACCOUNT_NAME']
        self._verifyStorageAccountName(storageAccount)
        status = self.client.getStorageAccountStatus(storageAccount)
        self.logger.info('      Storage Account: %s, Status: %s' %
                         (storageAccount, status))

        # ストレージアカウントが存在しない場合、作成する
        if status is None:
            affinityGroup = platformInfo['AFFINITY_GROUP_NAME']
            self.logger.debug('      Trying to create Storage Account: %s' %
                              (storageAccount))
            status = self.client.createStorageAccount(storageAccount,
                                                      affinityGroup)
            self.logger.info('      Storage Account: %s, Status: %s' %
                             (storageAccount, status))
        else:
            # ステータスが作成完了以外の場合の処理は要検討
            pass

    def _verifyStorageAccountName(self, storageAccount):
        pass
Ejemplo n.º 32
0
#
from iaasgw.log.log import IaasLogger
from iaasgw.utils.iaasSelecter import iaasSelect
import os
import sys
import traceback

#*****************************************************************
#
#  注)これはvCloudプラットフォーム専用のインターフェースとなります
#
#*****************************************************************

if __name__ == '__main__':
    param = sys.argv
    logger = IaasLogger()

    #ログ用パラメータ
    logparam = ["DeleteMyCloud", os.getpid(), "Farm ID:%s" % str(param[3])]
    logger.start(logparam)

    #実行
    try:
        #パラメータ解説
        #  0.ファイル名
        #  1.ユーザー名
        #  2.プラットフォームNo
        #  3.マイクラウド名
        #
        iaasController = iaasSelect(param[1], param[2])
        if iaasController == None:
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 # GNU General Public License for more details.
 # 
 # You should have received a copy of the GNU General Public License
 # along with PrimeCloud Controller(TM). If not, see <http://www.gnu.org/licenses/>.
 # 
from azure import *
from azure.servicemanagement import *
from azure.storage import BlobService
from iaasgw.log.log import IaasLogger
import traceback
import time

if __name__ == "__main__":

    logger = IaasLogger()

    argc = len(sys.argv)
    if (argc != 7):
        logger.error('deleteOSandDataDisk.py: Usage: python %s subscription certificateFilePath storageAccount accessKey mediaLink osHardDiskName' % sys.argv[0])
        sys.exit()

    subscription = sys.argv[1]
    certPath = sys.argv[2]
    storageAccount = sys.argv[3]
    accessKey = sys.argv[4]
    mediaLink = sys.argv[5]
    osHardDiskName = sys.argv[6]
  
    #--------------
    # Azureサービスオブジェクトを作成