diff --git a/WindowsAgent/.gitignore b/.gitignore similarity index 100% rename from WindowsAgent/.gitignore rename to .gitignore diff --git a/Deployment/ExecutionPlan/1.CreatePrimaryDC/CreatePrimaryDC.json b/Deployment/ExecutionPlan/1.CreatePrimaryDC/CreatePrimaryDC.json deleted file mode 100644 index 519da701..00000000 --- a/Deployment/ExecutionPlan/1.CreatePrimaryDC/CreatePrimaryDC.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "Scripts": [ - "DQpGdW5jdGlvbiBJbnN0YWxsLVJvbGVQcmltYXJ5RG9tYWluQ29udHJvbGxlcg0Kew0KPCMNCi5TWU5PUFNJUw0KQ29uZmlndXJlIG5vZGUncyBuZXR3b3JrIGFkYXB0ZXJzLg0KQ3JlYXRlIGZpcnN0IGRvbWFpbiBjb250cm9sbGVyIGluIHRoZSBmb3Jlc3QuDQoNCi5FWEFNUExFDQpQUz4gSW5zdGFsbC1Sb2xlUHJpbWFyeURvbWFpbkNvbnRyb2xsZXIgLURvbWFpbk5hbWUgYWNtZS5sb2NhbCAtU2FmZU1vZGVQYXNzd29yZCAiUEBzc3cwcmQiDQoNCkluc3RhbGwgRE5TIGFuZCBBRERTLCBjcmVhdGUgZm9yZXN0IGFuZCBkb21haW4gJ2FjbWUubG9jYWwnLg0KU2V0IERDIHJlY292ZXJ5IG1vZGUgcGFzc3dvcmQgdG8gJ1BAc3N3MHJkJy4NCiM+DQoJDQoJcGFyYW0NCgkoDQoJCVtTdHJpbmddDQoJCSMgTmV3IGRvbWFpbiBuYW1lLg0KCQkkRG9tYWluTmFtZSwNCgkJDQoJCVtTdHJpbmddDQoJCSMgRG9tYWluIGNvbnRyb2xsZXIgcmVjb3ZlcnkgbW9kZSBwYXNzd29yZC4NCgkJJFNhZmVNb2RlUGFzc3dvcmQNCgkpDQoNCgl0cmFwIHsgU3RvcC1FeGVjdXRpb24gJF8gfQ0KDQogICAgICAgICMgQWRkIHJlcXVpcmVkIHdpbmRvd3MgZmVhdHVyZXMNCglBZGQtV2luZG93c0ZlYXR1cmVXcmFwcGVyIGANCgkJLU5hbWUgIkROUyIsIkFELURvbWFpbi1TZXJ2aWNlcyIsIlJTQVQtREZTLU1nbXQtQ29uIiBgDQoJCS1JbmNsdWRlTWFuYWdlbWVudFRvb2xzIGANCiAgICAgICAgLU5vdGlmeVJlc3RhcnQNCg0KDQoJV3JpdGUtTG9nICJDcmVhdGluZyBmaXJzdCBkb21haW4gY29udHJvbGxlciAuLi4iDQoJCQ0KCSRTTUFQID0gQ29udmVydFRvLVNlY3VyZVN0cmluZyAtU3RyaW5nICRTYWZlTW9kZVBhc3N3b3JkIC1Bc1BsYWluVGV4dCAtRm9yY2UNCgkJDQoJSW5zdGFsbC1BRERTRm9yZXN0IGANCgkJLURvbWFpbk5hbWUgJERvbWFpbk5hbWUgYA0KCQktU2FmZU1vZGVBZG1pbmlzdHJhdG9yUGFzc3dvcmQgJFNNQVAgYA0KCQktRG9tYWluTW9kZSBEZWZhdWx0IGANCgkJLUZvcmVzdE1vZGUgRGVmYXVsdCBgDQoJCS1Ob1JlYm9vdE9uQ29tcGxldGlvbiBgDQoJCS1Gb3JjZSBgDQoJCS1FcnJvckFjdGlvbiBTdG9wIHwgT3V0LU51bGwNCg0KCVdyaXRlLUxvZyAiV2FpdGluZyBmb3IgcmVib290IC4uLiIJCQ0KIwlTdG9wLUV4ZWN1dGlvbiAtRXhpdENvZGUgMzAxMCAtRXhpdFN0cmluZyAiQ29tcHV0ZXIgbXVzdCBiZSByZXN0YXJ0ZWQgdG8gZmluaXNoIGRvbWFpbiBjb250cm9sbGVyIHByb21vdGlvbi4iDQojCVdyaXRlLUxvZyAiUmVzdGFyaW5nIGNvbXB1dGVyIC4uLiINCiMJUmVzdGFydC1Db21wdXRlciAtRm9yY2UNCn0NCg==" - ], - "Commands": [ - { - "Name": "Import-Module", - "Arguments": { - "Name": "CoreFunctions" - } - }, - { - "Name": "Set-LocalUserPassword", - "Arguments": { - "UserName": "Administrator", - "Password": "P@ssw0rd123", - "Force": true - } - }, - { - "Name": "Install-RolePrimaryDomainController", - "Arguments": { - "DomainName": "acme.local", - "SafeModePassword": "P@ssw0rd" - } - } - ], - "RebootOnCompletion": 1 -} \ No newline at end of file diff --git a/Deployment/ExecutionPlan/1.CreatePrimaryDC/ExecutionPlan.txt b/Deployment/ExecutionPlan/1.CreatePrimaryDC/ExecutionPlan.txt deleted file mode 100644 index 74524776..00000000 --- a/Deployment/ExecutionPlan/1.CreatePrimaryDC/ExecutionPlan.txt +++ /dev/null @@ -1,9 +0,0 @@ -include Install-RolePrimaryDomainController.ps1 - -call Import-Module Name="CoreFunctions" -call Set-LocalUserPassword UserName="Administrator" , Password="P@ssw0rd123" , Force=true -call Install-RolePrimaryDomainController DomainName="acme.local" , SafeModePassword="P@ssw0rd" - -reboot 1 - -out CreatePrimaryDC.json diff --git a/Deployment/ExecutionPlan/1.CreatePrimaryDC/GenerateJSON.bat b/Deployment/ExecutionPlan/1.CreatePrimaryDC/GenerateJSON.bat deleted file mode 100644 index 0b6aae7e..00000000 --- a/Deployment/ExecutionPlan/1.CreatePrimaryDC/GenerateJSON.bat +++ /dev/null @@ -1 +0,0 @@ -..\ExecutionPlanGenerator.exe ExecutionPlan.txt \ No newline at end of file diff --git a/Deployment/ExecutionPlan/1.CreatePrimaryDC/Install-RolePrimaryDomainController.ps1 b/Deployment/ExecutionPlan/1.CreatePrimaryDC/Install-RolePrimaryDomainController.ps1 deleted file mode 100644 index 165b8562..00000000 --- a/Deployment/ExecutionPlan/1.CreatePrimaryDC/Install-RolePrimaryDomainController.ps1 +++ /dev/null @@ -1,53 +0,0 @@ - -Function Install-RolePrimaryDomainController -{ -<# -.SYNOPSIS -Configure node's network adapters. -Create first domain controller in the forest. - -.EXAMPLE -PS> Install-RolePrimaryDomainController -DomainName acme.local -SafeModePassword "P@ssw0rd" - -Install DNS and ADDS, create forest and domain 'acme.local'. -Set DC recovery mode password to 'P@ssw0rd'. -#> - - param - ( - [String] - # New domain name. - $DomainName, - - [String] - # Domain controller recovery mode password. - $SafeModePassword - ) - - trap { Stop-Execution $_ } - - # Add required windows features - Add-WindowsFeatureWrapper ` - -Name "DNS","AD-Domain-Services","RSAT-DFS-Mgmt-Con" ` - -IncludeManagementTools ` - -NotifyRestart - - - Write-Log "Creating first domain controller ..." - - $SMAP = ConvertTo-SecureString -String $SafeModePassword -AsPlainText -Force - - Install-ADDSForest ` - -DomainName $DomainName ` - -SafeModeAdministratorPassword $SMAP ` - -DomainMode Default ` - -ForestMode Default ` - -NoRebootOnCompletion ` - -Force ` - -ErrorAction Stop | Out-Null - - Write-Log "Waiting for reboot ..." -# Stop-Execution -ExitCode 3010 -ExitString "Computer must be restarted to finish domain controller promotion." -# Write-Log "Restaring computer ..." -# Restart-Computer -Force -} diff --git a/Deployment/ExecutionPlan/2.JoinDomain/ExecutionPlan.txt b/Deployment/ExecutionPlan/2.JoinDomain/ExecutionPlan.txt deleted file mode 100644 index dafdc217..00000000 --- a/Deployment/ExecutionPlan/2.JoinDomain/ExecutionPlan.txt +++ /dev/null @@ -1,9 +0,0 @@ -call Import-Module Name="CoreFunctions" -call Set-NetworkAdapterConfiguration FirstAvailable=true , DNSServer="10.0.102.2" -call Join-Domain DomainName="acme.local" , Username="Administrator" , Password="P@ssw0rd123" - -reboot 1 - -out out.json - - diff --git a/Deployment/ExecutionPlan/2.JoinDomain/GenerateJSON.bat b/Deployment/ExecutionPlan/2.JoinDomain/GenerateJSON.bat deleted file mode 100644 index 0b6aae7e..00000000 --- a/Deployment/ExecutionPlan/2.JoinDomain/GenerateJSON.bat +++ /dev/null @@ -1 +0,0 @@ -..\ExecutionPlanGenerator.exe ExecutionPlan.txt \ No newline at end of file diff --git a/Deployment/ExecutionPlan/2.JoinDomain/out.json b/Deployment/ExecutionPlan/2.JoinDomain/out.json deleted file mode 100644 index 6905daa9..00000000 --- a/Deployment/ExecutionPlan/2.JoinDomain/out.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "Scripts": [], - "Commands": [ - { - "Name": "Import-Module", - "Arguments": { - "Name": "CoreFunctions" - } - }, - { - "Name": "Set-NetworkAdapterConfiguration", - "Arguments": { - "FirstAvailable": true, - "DNSServer": "10.0.102.2" - } - }, - { - "Name": "Join-Domain", - "Arguments": { - "DomainName": "acme.local", - "Username": "Administrator", - "Password": "P@ssw0rd123" - } - } - ], - "RebootOnCompletion": 1 -} \ No newline at end of file diff --git a/Deployment/ExecutionPlan/3.CreateSecondaryDC/ExecutionPlan.txt b/Deployment/ExecutionPlan/3.CreateSecondaryDC/ExecutionPlan.txt deleted file mode 100644 index dcffeaad..00000000 --- a/Deployment/ExecutionPlan/3.CreateSecondaryDC/ExecutionPlan.txt +++ /dev/null @@ -1,8 +0,0 @@ -include Install-RoleSecondaryDomainController.ps1 - -call Import-Module Name="CoreFunctions" -call Install-RoleSecondaryDomainController DomainName="acme.local" , UserName="Administrator" , Password="P@ssw0rd123" , SafeModePassword="P@ssw0rd" - -reboot 1 - -out out.json diff --git a/Deployment/ExecutionPlan/3.CreateSecondaryDC/GenerateJSON.bat b/Deployment/ExecutionPlan/3.CreateSecondaryDC/GenerateJSON.bat deleted file mode 100644 index 0b6aae7e..00000000 --- a/Deployment/ExecutionPlan/3.CreateSecondaryDC/GenerateJSON.bat +++ /dev/null @@ -1 +0,0 @@ -..\ExecutionPlanGenerator.exe ExecutionPlan.txt \ No newline at end of file diff --git a/Deployment/ExecutionPlan/3.CreateSecondaryDC/Install-RoleSecondaryDomainController.ps1 b/Deployment/ExecutionPlan/3.CreateSecondaryDC/Install-RoleSecondaryDomainController.ps1 deleted file mode 100644 index a638ce4f..00000000 --- a/Deployment/ExecutionPlan/3.CreateSecondaryDC/Install-RoleSecondaryDomainController.ps1 +++ /dev/null @@ -1,54 +0,0 @@ -Function Install-RoleSecondaryDomainController -{ -<# -.SYNOPSIS -Install additional (secondary) domain controller. - -#> - param - ( - [String] - # Domain name to join to. - $DomainName, - - [String] - # Domain user who is allowed to join computer to domain. - $UserName, - - [String] - # User's password. - $Password, - - [String] - # Domain controller recovery mode password. - $SafeModePassword - ) - - trap { Stop-Execution $_ } - - $Credential = New-Credential -UserName "$DomainName\$UserName" -Password $Password - - # Add required windows features - Add-WindowsFeatureWrapper ` - -Name "DNS","AD-Domain-Services","RSAT-DFS-Mgmt-Con" ` - -IncludeManagementTools ` - -NotifyRestart - - - Write-Log "Adding secondary domain controller ..." - - $SMAP = ConvertTo-SecureString -String $SafeModePassword -AsPlainText -Force - - Install-ADDSDomainController ` - -DomainName $DomainName ` - -SafeModeAdministratorPassword $SMAP ` - -Credential $Credential ` - -NoRebootOnCompletion ` - -Force ` - -ErrorAction Stop | Out-Null - - Write-Log "Waiting for restart ..." -# Stop-Execution -ExitCode 3010 -ExitString "Computer must be restarted to finish domain controller promotion." -# Write-Log "Restarting computer ..." -# Restart-Computer -Force -} diff --git a/Deployment/ExecutionPlan/3.CreateSecondaryDC/out.json b/Deployment/ExecutionPlan/3.CreateSecondaryDC/out.json deleted file mode 100644 index 6f260a2b..00000000 --- a/Deployment/ExecutionPlan/3.CreateSecondaryDC/out.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "Scripts": [ - "RnVuY3Rpb24gSW5zdGFsbC1Sb2xlU2Vjb25kYXJ5RG9tYWluQ29udHJvbGxlcg0Kew0KPCMNCi5TWU5PUFNJUw0KSW5zdGFsbCBhZGRpdGlvbmFsIChzZWNvbmRhcnkpIGRvbWFpbiBjb250cm9sbGVyLg0KDQojPg0KCXBhcmFtDQoJKA0KCQlbU3RyaW5nXQ0KCQkjIERvbWFpbiBuYW1lIHRvIGpvaW4gdG8uDQoJCSREb21haW5OYW1lLA0KCQkNCgkJW1N0cmluZ10NCgkJIyBEb21haW4gdXNlciB3aG8gaXMgYWxsb3dlZCB0byBqb2luIGNvbXB1dGVyIHRvIGRvbWFpbi4NCgkJJFVzZXJOYW1lLA0KCQkNCgkJW1N0cmluZ10NCgkJIyBVc2VyJ3MgcGFzc3dvcmQuDQoJCSRQYXNzd29yZCwNCgkJDQoJCVtTdHJpbmddDQoJCSMgRG9tYWluIGNvbnRyb2xsZXIgcmVjb3ZlcnkgbW9kZSBwYXNzd29yZC4NCgkJJFNhZmVNb2RlUGFzc3dvcmQNCgkpDQoNCgl0cmFwIHsgU3RvcC1FeGVjdXRpb24gJF8gfQ0KCQ0KCSRDcmVkZW50aWFsID0gTmV3LUNyZWRlbnRpYWwgLVVzZXJOYW1lICIkRG9tYWluTmFtZVwkVXNlck5hbWUiIC1QYXNzd29yZCAkUGFzc3dvcmQNCgkJDQoJIyBBZGQgcmVxdWlyZWQgd2luZG93cyBmZWF0dXJlcw0KCUFkZC1XaW5kb3dzRmVhdHVyZVdyYXBwZXIgYA0KCQktTmFtZSAiRE5TIiwiQUQtRG9tYWluLVNlcnZpY2VzIiwiUlNBVC1ERlMtTWdtdC1Db24iIGANCgkJLUluY2x1ZGVNYW5hZ2VtZW50VG9vbHMgYA0KICAgICAgICAgICAgICAgIC1Ob3RpZnlSZXN0YXJ0DQoJCQ0KCQ0KICAgICAgICBXcml0ZS1Mb2cgIkFkZGluZyBzZWNvbmRhcnkgZG9tYWluIGNvbnRyb2xsZXIgLi4uIg0KICAgIA0KCSRTTUFQID0gQ29udmVydFRvLVNlY3VyZVN0cmluZyAtU3RyaW5nICRTYWZlTW9kZVBhc3N3b3JkIC1Bc1BsYWluVGV4dCAtRm9yY2UNCg0KCUluc3RhbGwtQUREU0RvbWFpbkNvbnRyb2xsZXIgYA0KCQktRG9tYWluTmFtZSAkRG9tYWluTmFtZSBgDQoJCS1TYWZlTW9kZUFkbWluaXN0cmF0b3JQYXNzd29yZCAkU01BUCBgDQoJCS1DcmVkZW50aWFsICRDcmVkZW50aWFsIGANCgkJLU5vUmVib290T25Db21wbGV0aW9uIGANCgkJLUZvcmNlIGANCgkJLUVycm9yQWN0aW9uIFN0b3AgfCBPdXQtTnVsbA0KDQoJV3JpdGUtTG9nICJXYWl0aW5nIGZvciByZXN0YXJ0IC4uLiINCiMJU3RvcC1FeGVjdXRpb24gLUV4aXRDb2RlIDMwMTAgLUV4aXRTdHJpbmcgIkNvbXB1dGVyIG11c3QgYmUgcmVzdGFydGVkIHRvIGZpbmlzaCBkb21haW4gY29udHJvbGxlciBwcm9tb3Rpb24uIg0KIwlXcml0ZS1Mb2cgIlJlc3RhcnRpbmcgY29tcHV0ZXIgLi4uIg0KIwlSZXN0YXJ0LUNvbXB1dGVyIC1Gb3JjZQ0KfQ0K" - ], - "Commands": [ - { - "Name": "Import-Module", - "Arguments": { - "Name": "CoreFunctions" - } - }, - { - "Name": "Install-RoleSecondaryDomainController", - "Arguments": { - "DomainName": "acme.local", - "UserName": "Administrator", - "Password": "P@ssw0rd123", - "SafeModePassword": "P@ssw0rd" - } - } - ], - "RebootOnCompletion": 1 -} \ No newline at end of file diff --git a/Deployment/ExecutionPlan/4.JoinAndPromote/ExecutionPlan.txt b/Deployment/ExecutionPlan/4.JoinAndPromote/ExecutionPlan.txt deleted file mode 100644 index 076f569b..00000000 --- a/Deployment/ExecutionPlan/4.JoinAndPromote/ExecutionPlan.txt +++ /dev/null @@ -1,10 +0,0 @@ -include Install-RoleSecondaryDomainController.ps1 - -call Import-Module Name="CoreFunctions" -call Set-NetworkAdapterConfiguration FirstAvailable=true , DNSServer="10.0.102.2" -call Join-Domain DomainName="acme.local" , Username="Administrator" , Password="P@ssw0rd123" , AllowRestart=true -call Install-RoleSecondaryDomainController DomainName="acme.local" , UserName="Administrator" , Password="P@ssw0rd123" , SafeModePassword="P@ssw0rd" - -reboot 1 - -out out.json diff --git a/Deployment/ExecutionPlan/4.JoinAndPromote/GenerateJSON.bat b/Deployment/ExecutionPlan/4.JoinAndPromote/GenerateJSON.bat deleted file mode 100644 index 0b6aae7e..00000000 --- a/Deployment/ExecutionPlan/4.JoinAndPromote/GenerateJSON.bat +++ /dev/null @@ -1 +0,0 @@ -..\ExecutionPlanGenerator.exe ExecutionPlan.txt \ No newline at end of file diff --git a/Deployment/ExecutionPlan/4.JoinAndPromote/Install-RoleSecondaryDomainController.ps1 b/Deployment/ExecutionPlan/4.JoinAndPromote/Install-RoleSecondaryDomainController.ps1 deleted file mode 100644 index a638ce4f..00000000 --- a/Deployment/ExecutionPlan/4.JoinAndPromote/Install-RoleSecondaryDomainController.ps1 +++ /dev/null @@ -1,54 +0,0 @@ -Function Install-RoleSecondaryDomainController -{ -<# -.SYNOPSIS -Install additional (secondary) domain controller. - -#> - param - ( - [String] - # Domain name to join to. - $DomainName, - - [String] - # Domain user who is allowed to join computer to domain. - $UserName, - - [String] - # User's password. - $Password, - - [String] - # Domain controller recovery mode password. - $SafeModePassword - ) - - trap { Stop-Execution $_ } - - $Credential = New-Credential -UserName "$DomainName\$UserName" -Password $Password - - # Add required windows features - Add-WindowsFeatureWrapper ` - -Name "DNS","AD-Domain-Services","RSAT-DFS-Mgmt-Con" ` - -IncludeManagementTools ` - -NotifyRestart - - - Write-Log "Adding secondary domain controller ..." - - $SMAP = ConvertTo-SecureString -String $SafeModePassword -AsPlainText -Force - - Install-ADDSDomainController ` - -DomainName $DomainName ` - -SafeModeAdministratorPassword $SMAP ` - -Credential $Credential ` - -NoRebootOnCompletion ` - -Force ` - -ErrorAction Stop | Out-Null - - Write-Log "Waiting for restart ..." -# Stop-Execution -ExitCode 3010 -ExitString "Computer must be restarted to finish domain controller promotion." -# Write-Log "Restarting computer ..." -# Restart-Computer -Force -} diff --git a/Deployment/ExecutionPlan/4.JoinAndPromote/out.json b/Deployment/ExecutionPlan/4.JoinAndPromote/out.json deleted file mode 100644 index cd6fe954..00000000 --- a/Deployment/ExecutionPlan/4.JoinAndPromote/out.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "Scripts": [ - "RnVuY3Rpb24gSW5zdGFsbC1Sb2xlU2Vjb25kYXJ5RG9tYWluQ29udHJvbGxlcg0Kew0KPCMNCi5TWU5PUFNJUw0KSW5zdGFsbCBhZGRpdGlvbmFsIChzZWNvbmRhcnkpIGRvbWFpbiBjb250cm9sbGVyLg0KDQojPg0KCXBhcmFtDQoJKA0KCQlbU3RyaW5nXQ0KCQkjIERvbWFpbiBuYW1lIHRvIGpvaW4gdG8uDQoJCSREb21haW5OYW1lLA0KCQkNCgkJW1N0cmluZ10NCgkJIyBEb21haW4gdXNlciB3aG8gaXMgYWxsb3dlZCB0byBqb2luIGNvbXB1dGVyIHRvIGRvbWFpbi4NCgkJJFVzZXJOYW1lLA0KCQkNCgkJW1N0cmluZ10NCgkJIyBVc2VyJ3MgcGFzc3dvcmQuDQoJCSRQYXNzd29yZCwNCgkJDQoJCVtTdHJpbmddDQoJCSMgRG9tYWluIGNvbnRyb2xsZXIgcmVjb3ZlcnkgbW9kZSBwYXNzd29yZC4NCgkJJFNhZmVNb2RlUGFzc3dvcmQNCgkpDQoNCgl0cmFwIHsgU3RvcC1FeGVjdXRpb24gJF8gfQ0KCQ0KCSRDcmVkZW50aWFsID0gTmV3LUNyZWRlbnRpYWwgLVVzZXJOYW1lICIkRG9tYWluTmFtZVwkVXNlck5hbWUiIC1QYXNzd29yZCAkUGFzc3dvcmQNCgkJDQoJIyBBZGQgcmVxdWlyZWQgd2luZG93cyBmZWF0dXJlcw0KCUFkZC1XaW5kb3dzRmVhdHVyZVdyYXBwZXIgYA0KCQktTmFtZSAiRE5TIiwiQUQtRG9tYWluLVNlcnZpY2VzIiwiUlNBVC1ERlMtTWdtdC1Db24iIGANCgkJLUluY2x1ZGVNYW5hZ2VtZW50VG9vbHMgYA0KICAgICAgICAgICAgICAgIC1Ob3RpZnlSZXN0YXJ0DQoJCQ0KCQ0KICAgICAgICBXcml0ZS1Mb2cgIkFkZGluZyBzZWNvbmRhcnkgZG9tYWluIGNvbnRyb2xsZXIgLi4uIg0KICAgIA0KCSRTTUFQID0gQ29udmVydFRvLVNlY3VyZVN0cmluZyAtU3RyaW5nICRTYWZlTW9kZVBhc3N3b3JkIC1Bc1BsYWluVGV4dCAtRm9yY2UNCg0KCUluc3RhbGwtQUREU0RvbWFpbkNvbnRyb2xsZXIgYA0KCQktRG9tYWluTmFtZSAkRG9tYWluTmFtZSBgDQoJCS1TYWZlTW9kZUFkbWluaXN0cmF0b3JQYXNzd29yZCAkU01BUCBgDQoJCS1DcmVkZW50aWFsICRDcmVkZW50aWFsIGANCgkJLU5vUmVib290T25Db21wbGV0aW9uIGANCgkJLUZvcmNlIGANCgkJLUVycm9yQWN0aW9uIFN0b3AgfCBPdXQtTnVsbA0KDQoJV3JpdGUtTG9nICJXYWl0aW5nIGZvciByZXN0YXJ0IC4uLiINCiMJU3RvcC1FeGVjdXRpb24gLUV4aXRDb2RlIDMwMTAgLUV4aXRTdHJpbmcgIkNvbXB1dGVyIG11c3QgYmUgcmVzdGFydGVkIHRvIGZpbmlzaCBkb21haW4gY29udHJvbGxlciBwcm9tb3Rpb24uIg0KIwlXcml0ZS1Mb2cgIlJlc3RhcnRpbmcgY29tcHV0ZXIgLi4uIg0KIwlSZXN0YXJ0LUNvbXB1dGVyIC1Gb3JjZQ0KfQ0K" - ], - "Commands": [ - { - "Name": "Import-Module", - "Arguments": { - "Name": "CoreFunctions" - } - }, - { - "Name": "Set-NetworkAdapterConfiguration", - "Arguments": { - "FirstAvailable": true, - "DNSServer": "10.0.102.2" - } - }, - { - "Name": "Join-Domain", - "Arguments": { - "DomainName": "acme.local", - "Username": "Administrator", - "Password": "P@ssw0rd123", - "AllowRestart": true - } - }, - { - "Name": "Install-RoleSecondaryDomainController", - "Arguments": { - "DomainName": "acme.local", - "UserName": "Administrator", - "Password": "P@ssw0rd123", - "SafeModePassword": "P@ssw0rd" - } - } - ], - "RebootOnCompletion": 1 -} \ No newline at end of file diff --git a/Deployment/ExecutionPlan/ExecutionPlanGenerator.exe b/Deployment/ExecutionPlan/ExecutionPlanGenerator.exe deleted file mode 100644 index ef78c02d..00000000 Binary files a/Deployment/ExecutionPlan/ExecutionPlanGenerator.exe and /dev/null differ diff --git a/Deployment/ExecutionPlan/GetDnsIpAddressesOnDc/ExecutionPlan.txt b/Deployment/ExecutionPlan/GetDnsIpAddressesOnDc/ExecutionPlan.txt deleted file mode 100644 index 8440ea57..00000000 --- a/Deployment/ExecutionPlan/GetDnsIpAddressesOnDc/ExecutionPlan.txt +++ /dev/null @@ -1,7 +0,0 @@ -include Get-DnsListeningIpAddress.ps1 - -call Get-DnsListeningIpAddress - -reboot 0 - -out out.json diff --git a/Deployment/ExecutionPlan/GetDnsIpAddressesOnDc/GenerateJSON.bat b/Deployment/ExecutionPlan/GetDnsIpAddressesOnDc/GenerateJSON.bat deleted file mode 100644 index 0b6aae7e..00000000 --- a/Deployment/ExecutionPlan/GetDnsIpAddressesOnDc/GenerateJSON.bat +++ /dev/null @@ -1 +0,0 @@ -..\ExecutionPlanGenerator.exe ExecutionPlan.txt \ No newline at end of file diff --git a/Deployment/ExecutionPlan/GetDnsIpAddressesOnDc/Get-DnsListeningIpAddress.ps1 b/Deployment/ExecutionPlan/GetDnsIpAddressesOnDc/Get-DnsListeningIpAddress.ps1 deleted file mode 100644 index 421464d7..00000000 --- a/Deployment/ExecutionPlan/GetDnsIpAddressesOnDc/Get-DnsListeningIpAddress.ps1 +++ /dev/null @@ -1,5 +0,0 @@ -function Get-DnsListeningIpAddress { - Import-Module DnsServer - (Get-DNSServer -ComputerName localhost).ServerSetting.ListeningIpAddress | - Where-Object { $_ -match "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" } -} diff --git a/Deployment/ExecutionPlan/GetDnsIpAddressesOnDc/out.json b/Deployment/ExecutionPlan/GetDnsIpAddressesOnDc/out.json deleted file mode 100644 index a9f6ee38..00000000 --- a/Deployment/ExecutionPlan/GetDnsIpAddressesOnDc/out.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "Scripts": [ - "ZnVuY3Rpb24gR2V0LURuc0xpc3RlbmluZ0lwQWRkcmVzcyB7DQogICAgSW1wb3J0LU1vZHVsZSBEbnNTZXJ2ZXINCiAgICAoR2V0LUROU1NlcnZlciAtQ29tcHV0ZXJOYW1lIGxvY2FsaG9zdCkuU2VydmVyU2V0dGluZy5MaXN0ZW5pbmdJcEFkZHJlc3MgfA0KICAgICAgICBXaGVyZS1PYmplY3QgeyAkXyAtbWF0Y2ggIlxkezEsM31cLlxkezEsM31cLlxkezEsM31cLlxkezEsM30iIH0NCn0NCg==" - ], - "Commands": [ - { - "Name": "Get-DnsListeningIpAddress", - "Arguments": {} - } - ], - "RebootOnCompletion": 0 -} \ No newline at end of file diff --git a/Deployment/ExecutionPlan/InstallIIS/ExecutionPlan.txt b/Deployment/ExecutionPlan/InstallIIS/ExecutionPlan.txt deleted file mode 100644 index bf3d2e97..00000000 --- a/Deployment/ExecutionPlan/InstallIIS/ExecutionPlan.txt +++ /dev/null @@ -1,7 +0,0 @@ -include Install-WebServer.ps1 - -call Install-WebServer - -reboot 0 - -out out.json diff --git a/Deployment/ExecutionPlan/InstallIIS/GenerateJSON.bat b/Deployment/ExecutionPlan/InstallIIS/GenerateJSON.bat deleted file mode 100644 index 0b6aae7e..00000000 --- a/Deployment/ExecutionPlan/InstallIIS/GenerateJSON.bat +++ /dev/null @@ -1 +0,0 @@ -..\ExecutionPlanGenerator.exe ExecutionPlan.txt \ No newline at end of file diff --git a/Deployment/ExecutionPlan/InstallIIS/Install-WebServer.ps1 b/Deployment/ExecutionPlan/InstallIIS/Install-WebServer.ps1 deleted file mode 100644 index 5ec0a4be..00000000 --- a/Deployment/ExecutionPlan/InstallIIS/Install-WebServer.ps1 +++ /dev/null @@ -1,4 +0,0 @@ -function Install-WebServer { - Import-Module ServerManager - Install-WindowsFeature Web-Server -IncludeManagementTools -} diff --git a/Deployment/ExecutionPlan/InstallIIS/out.json b/Deployment/ExecutionPlan/InstallIIS/out.json deleted file mode 100644 index baeaec15..00000000 --- a/Deployment/ExecutionPlan/InstallIIS/out.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "Scripts": [ - "ZnVuY3Rpb24gSW5zdGFsbC1XZWJTZXJ2ZXIgew0KICAgIEltcG9ydC1Nb2R1bGUgU2VydmVyTWFuYWdlcg0KICAgIEluc3RhbGwtV2luZG93c0ZlYXR1cmUgV2ViLVNlcnZlciAtSW5jbHVkZU1hbmFnZW1lbnRUb29scw0KfQ0K" - ], - "Commands": [ - { - "Name": "Install-WebServer", - "Arguments": {} - } - ], - "RebootOnCompletion": 0 -} \ No newline at end of file diff --git a/Deployment/ExecutionPlan/Newtonsoft.Json.dll b/Deployment/ExecutionPlan/Newtonsoft.Json.dll deleted file mode 100644 index 81639f9b..00000000 Binary files a/Deployment/ExecutionPlan/Newtonsoft.Json.dll and /dev/null differ diff --git a/Deployment/Unattended/ws-2012-core-unattended.xml b/Deployment/Unattended/ws-2012-core-unattended.xml deleted file mode 100644 index b01499dd..00000000 --- a/Deployment/Unattended/ws-2012-core-unattended.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - Pacific Standard Time - - - - - - - UABAAHMAcwB3ADAAcgBkAFAAYQBzAHMAdwBvAHIAZAA= - false</PlainText> - </Password> - <Username>Administrator</Username> - <LogonCount>1</LogonCount> - <Enabled>false</Enabled> - </AutoLogon> - <UserAccounts> - <AdministratorPassword> - <Value>UABAAHMAcwB3ADAAcgBkAEEAZABtAGkAbgBpAHMAdAByAGEAdABvAHIAUABhAHMAcwB3AG8AcgBkAA==</Value> - <PlainText>false</PlainText> - </AdministratorPassword> - </UserAccounts> - <RegisteredOrganization>-</RegisteredOrganization> - <RegisteredOwner>-</RegisteredOwner> - <OOBE> - <HideEULAPage>true</HideEULAPage> - </OOBE> - </component> - <component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> - <InputLocale>en-US</InputLocale> - <SystemLocale>en-US</SystemLocale> - <UILanguage>en-US</UILanguage> - <UserLocale>en-US</UserLocale> - </component> - </settings> - <settings pass="generalize"> - <component name="Microsoft-Windows-Security-SPP" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> - <SkipRearm>1</SkipRearm> - </component> - </settings> - <cpi:offlineImage cpi:source="wim:d:/aik/install.wim#Windows Server 2012 SERVERSTANDARDCORE" xmlns:cpi="urn:schemas-microsoft-com:cpi" /> -</unattend> diff --git a/Deployment/Unattended/ws-2012-full-unattend.xml b/Deployment/Unattended/ws-2012-full-unattend.xml deleted file mode 100644 index 78961363..00000000 --- a/Deployment/Unattended/ws-2012-full-unattend.xml +++ /dev/null @@ -1,51 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<unattend xmlns="urn:schemas-microsoft-com:unattend"> - <settings pass="specialize"> - <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> - <TimeZone>Pacific Stantard Time</TimeZone> - </component> - </settings> - <settings pass="oobeSystem"> - <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> - <AutoLogon> - <Password> - <Value>UABAAHMAcwB3ADAAcgBkAFAAYQBzAHMAdwBvAHIAZAA=</Value> - <PlainText>false</PlainText> - </Password> - <LogonCount>1</LogonCount> - <Username>Administrator</Username> - <Enabled>true</Enabled> - </AutoLogon> - <UserAccounts> - <AdministratorPassword> - <Value>UABAAHMAcwB3ADAAcgBkAEEAZABtAGkAbgBpAHMAdAByAGEAdABvAHIAUABhAHMAcwB3AG8AcgBkAA==</Value> - <PlainText>false</PlainText> - </AdministratorPassword> - </UserAccounts> - <RegisteredOrganization>-</RegisteredOrganization> - <RegisteredOwner>-</RegisteredOwner> - <OOBE> - <HideEULAPage>true</HideEULAPage> - </OOBE> - <FirstLogonCommands> - <SynchronousCommand wcm:action="add"> - <RequiresUserInput>true</RequiresUserInput> - <CommandLine>powershell.exe -File C:\Deploy\Scripts\FirstLogon.ps1</CommandLine> - <Order>1</Order> - </SynchronousCommand> - </FirstLogonCommands> - </component> - <component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> - <InputLocale>en-US</InputLocale> - <SystemLocale>en-US</SystemLocale> - <UILanguage>en-US</UILanguage> - <UserLocale>en-US</UserLocale> - </component> - </settings> - <settings pass="generalize"> - <component name="Microsoft-Windows-Security-SPP" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> - <SkipRearm>1</SkipRearm> - </component> - </settings> - <cpi:offlineImage cpi:source="wim:d:/aik/install.wim#Windows Server 2012 SERVERSTANDARD" xmlns:cpi="urn:schemas-microsoft-com:cpi" /> -</unattend> diff --git a/Deployment/WindowsPowerShell/Modules/CoreFunctions/Config.ps1 b/Deployment/WindowsPowerShell/Modules/CoreFunctions/Config.ps1 deleted file mode 100644 index 79a2f9e2..00000000 --- a/Deployment/WindowsPowerShell/Modules/CoreFunctions/Config.ps1 +++ /dev/null @@ -1,28 +0,0 @@ -<# -Naming convention: - -== Normal variables -** Set: $NormalVar = 123 -** Get: Write-Host $NormalVar - -== Script-scope variables -** Set: $script:__ScriptScopeVar = 123 -** Get: Write-Host $__ScriptScopeVar - -== Global-scope variables -** Set: $global:__GlobalScopeVar__ = 123 -** Get: Write-Host $__GlobalScopeVar__ -#> - -$script:__ModulePath = $PsScriptRoot -$script:__ModuleName = $PsScriptRoot.Split("\")[-1] -$script:__DefaultLogPath = [IO.Path]::Combine([IO.Path]::GetTempPath(), "PowerShell_$__ModuleName.log") - - -$script:__RequiredModules = @("ServerManager", "DnsClient") -$script:__ImportModulesExplicitely = $true -$script:__ImportModulesErrorAction = "Stop" - - -$global:__StopExecutionPreference__ = "Exit" - diff --git a/Deployment/WindowsPowerShell/Modules/CoreFunctions/CoreFunctions.psd1 b/Deployment/WindowsPowerShell/Modules/CoreFunctions/CoreFunctions.psd1 deleted file mode 100644 index 0d52bf70..00000000 Binary files a/Deployment/WindowsPowerShell/Modules/CoreFunctions/CoreFunctions.psd1 and /dev/null differ diff --git a/Deployment/WindowsPowerShell/Modules/CoreFunctions/CoreFunctions.psm1 b/Deployment/WindowsPowerShell/Modules/CoreFunctions/CoreFunctions.psm1 deleted file mode 100644 index 9e72136b..00000000 --- a/Deployment/WindowsPowerShell/Modules/CoreFunctions/CoreFunctions.psm1 +++ /dev/null @@ -1,36 +0,0 @@ -# Import config first -. "$PsScriptRoot\Config.ps1" - -# Import functions from 'Include' subfolder -Get-ChildItem "$PsScriptRoot\Include" -Filter "*.ps1" | - ForEach-Object { - . "$($_.FullName)" - } - -trap { Stop-Execution $_ } - -Export-ModuleMember -Function * -Alias * - -<# -if ($__ImportModulesExplicitely) { - foreach ($Module in $__RequiredModules) { - Write-Log "Importing module '$Module' ..." - Import-Module -Name "$Module" -ErrorAction "$__ImportModulesErrorAction" - } -} -#> - -Write-Log "Module loaded from '$PsScriptRoot'" - -#------------------------------------------------------------------------------- - -switch ($Args[0]) { - 'installTo' { - Install-Module -InstallPath $args[1] -ModulePath $PsScriptRoot - } - 'register' { - Register-Module "$PsScriptRoot" - } - default { - } -} diff --git a/Deployment/WindowsPowerShell/Modules/CoreFunctions/Ionic.Zip.dll b/Deployment/WindowsPowerShell/Modules/CoreFunctions/Ionic.Zip.dll deleted file mode 100644 index 95fa9288..00000000 Binary files a/Deployment/WindowsPowerShell/Modules/CoreFunctions/Ionic.Zip.dll and /dev/null differ diff --git a/Deployment/WindowsPowerShell/Modules/CoreFunctions/en-US/about_CoreFunctions.help.txt b/Deployment/WindowsPowerShell/Modules/CoreFunctions/en-US/about_CoreFunctions.help.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/Deployment/WindowsPowerShell/Modules/CoreFunctions/include/Base64.ps1 b/Deployment/WindowsPowerShell/Modules/CoreFunctions/include/Base64.ps1 deleted file mode 100644 index 50bb4cf7..00000000 --- a/Deployment/WindowsPowerShell/Modules/CoreFunctions/include/Base64.ps1 +++ /dev/null @@ -1,99 +0,0 @@ - -Function ConvertTo-Base64String { -<# -#> - [CmdletBinding(DefaultParameterSetName="FromString")] - param ( - [Parameter(Position=1,ParameterSetName="FromString")] - [String] $String, - - [Parameter(ParameterSetName="FromFile")] - [String] $Path, - - [Parameter(ParameterSetName="FromFile")] - [Int] $ChunkSize = 5KB, - - [Parameter(ParameterSetName="FromFile")] - [Switch] $OneChunk - ) - switch($PSCmdlet.ParameterSetName) { - "FromString" { - [System.Text.Encoding]::UTF8.GetBytes($String) - [System.Convert]::ToBase64String($Bytes) - } - "FromFile" { - $FileStream = [IO.File]::Open($Path, [System.IO.FileMode]::Open) - $BytesToRead = $FileStream.Length - - if ($OneChunk) { - $ChunkSize = $BytesToRead - } - - $Bytes = New-Object Byte[] $ChunkSize - while ($BytesToRead -gt 0) { - if ($BytesToRead -lt $ChunkSize) { - $ChunkSize = $BytesToRead - $Bytes = New-Object Byte[] $ChunkSize - } - #Write-Host ("BytesToRead: {0}, ChunkSize: {1}" -f $BytesToRead, $ChunkSize ) - $BytesRead = $FileStream.Read($Bytes, 0, $ChunkSize) - $BytesToRead -= $BytesRead - - [System.Convert]::ToBase64String($Bytes) - } - $FileStream.Close() - } - } -} - - - -Function ConvertFrom-Base64String { -<# -#> - [CmdletBinding(DefaultParameterSetName="ToByteArray")] - param ( - [Parameter(Position=1,ValueFromPipeline=$true)] - [String] $Base64String, - - [Parameter(ParameterSetName="ToFile")] - [String] $Path, - - [Parameter(ParameterSetName="ToString")] - [Switch] $ToString - ) - begin { - switch($PSCmdlet.ParameterSetName) { - "ToFile" { - if ([IO.File]::Exists($Path)) { - [IO.File]::Delete($Path) - } - $FileStream = [IO.File]::Open($Path, [IO.FileMode]::Append) - } - } - } - process { - foreach( $Line in ($Base64String -split '\n')) { - $Bytes = [System.Convert]::FromBase64String($Line) - - switch($PSCmdlet.ParameterSetName) { - "ToFile" { - $FileStream.Write($Bytes, 0, $Bytes.Length) - } - "ToString" { - [System.Text.Encoding]::UTF8.GetString($Bytes) - } - "ToByteArray" { - $Bytes - } - } - } - } - end { - switch($PSCmdlet.ParameterSetName) { - "ToFile" { - $FileStream.Close() - } - } - } -} diff --git a/Deployment/WindowsPowerShell/Modules/CoreFunctions/include/Functions.ps1 b/Deployment/WindowsPowerShell/Modules/CoreFunctions/include/Functions.ps1 deleted file mode 100644 index 86cb0fb6..00000000 --- a/Deployment/WindowsPowerShell/Modules/CoreFunctions/include/Functions.ps1 +++ /dev/null @@ -1,388 +0,0 @@ -Function Stop-Execution { -<# -.SYNOPSIS -Breaks execution with specified error code. - -.DESCRIPTION -Function break script execution with error code provided. Error code may be 0 in case of non-error stop. - -It also tries to parse ErrorRecord or Exception object (if provided) and logs this information. -#> - [CmdletBinding(DefaultParameterSetName="Exception")] - - param ( - [Parameter(Position=1,ParameterSetName="Exception")] - $InputObject = $null, - - [Parameter(ParameterSetName="ErrorString")] - [String] $ExitString = "", - - [Parameter(ParameterSetName="ErrorString")] - [Int] $ExitCode = 0, - - [Parameter(ParameterSetName="ErrorString")] - [Switch] $Success - ) - - Function Exit-Function { - if ($ExitCode -eq 0) { - Write-LogInfo ( "STOP ({0}):`n{1}" -f $ExitCode, $ExitString ) - } - else { - Write-LogFatal ( "STOP ({0}):`n{1}" -f $ExitCode, $ExitString ) - } - - Write-Log "__StopExecutionPreference__ = '$__StopExecutionPreference__'" - switch ("$__StopExecutionPreference__") { - "Exit" { - exit $ExitCode - } - "ThrowIfException" { - if ($InputObject -eq $null) { - exit $ExitCode - } - else { - throw $InputObject - } - } - "ThrowAlways" { - throw $InputObject - } - default { - throw "Unknown value for __StopExecutionPreference__: '$__StopExecutionPreference__'" - } - } - } - - switch($PSCmdlet.ParameterSetName) { - "Exception" { - #---------- - if ($InputObject -eq $null) { - $ExitString = "***** SCRIPT INTERRUPTED *****" - $ExitCode = 255 - Exit-Function - } - #---------- - - - #---------- - try { - $ErrorRecord = [System.Management.Automation.ErrorRecord] $InputObject -<# - $ExitString = @" -$($ErrorRecord.ToString()) - -*** Invocation Info *** -$($ErrorRecord.InvocationInfo.PositionMessage) - -*** CategoryInfo *** -$($ErrorRecord.CategoryInfo.ToString()) - -*** FullyQualifiedErrorId *** -$($ErrorRecord.FullyQualifiedErrorId.ToString()) - -*** ScriptStackTrace *** -$($ErrorRecord.ScriptStackTrace.ToString()) -*** *** *** -"@ -#> - $ExitString = Out-String -InputObject $InputObject - $ExitCode = 255 - Exit-Function - } - catch { - $ErrorRecord = $null - Write-LogWarning "Unable to cast InputObject to [System.Management.Automation.ErrorRecord]" - } - #---------- - - - #---------- - try { - $Exception = [System.Exception] $InputObject - #$ExitString = $Exception.ToString() - $ExitString = Out-String -InputObject $InputObject - $ExitCode = 255 - Exit-Function - } - catch { - $Exception = $null - Write-LogWarning "Unable to cast InputObject to [System.Exception]" - } - #---------- - - - #---------- - try { - $ExitString = Out-String -InputObject $InputObject - $ExitCode = 255 - Exit-Function - } - catch { - Write-LogWarning "Unable to cast InputObject of type [$($InputObject.GetType())] to any of supported types." - } - #---------- - } - "ErrorString" { - if ($Success) { - $ExitString = "Script stopped with NO ERROR." - $ExitCode = 0 - } - - Exit-Function - } - } - - $ExitString = "Unknown error occured in Stop-Execution" - $ExitCode = 255 - Exit-Function -} - - - -Function Get-PasswordAsSecureString { -<# -.SYNOPSIS -Convert to / request password as secure string. -#> - [CmdletBinding()] - param ( - [String] $Password = "", - [String] $Prompt = "Please enter password" - ) - - if ($Password -eq "") { - Read-Host -Prompt $Prompt -AsSecureString - } - else { - ConvertTo-SecureString -String "$Password" -AsPlainText -Force - } -} - - - -Function New-Credential { -<# -.SYNOPSIS -Create new creadential object with username and password provided. -#> - [CmdletBinding()] - param ( - [Parameter(Mandatory=$true)] - [String] $UserName, - - [String] $Password - ) - - $SecurePassword = Get-PasswordAsSecureString -Password "$Password" - New-Object System.Management.Automation.PSCredential( "$UserName", $SecurePassword ) -} - - - -Function Invoke-WMSettingsChange { - if (-not ("win32.nativemethods" -as [type])) { - # Import SendMessageTimeout from Win32 - Add-Type -Namespace Win32 -Name NativeMethods -MemberDefinition @" -[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] -public static extern IntPtr SendMessageTimeout( - IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam, - uint fuFlags, uint uTimeout, out UIntPtr lpdwResult); -"@ - } - - $HWND_BROADCAST = [IntPtr]0xFFFF - $WM_SETTINGCHANGE = 0x001A - $result = [UIntPtr]::Zero - - # Notify all windows of environment block change - Write-Log "Executing 'SendMessageTimeout' ..." - - $retval = [Win32.NativeMethods]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE, - [UIntPtr]::Zero, "Environment", 2, 5000, [ref] $result) - - Write-Log "'SendMessageTimeout' returned '$retval' (non-zero is OK)" -} - - - -Function Start-Program { - param ( - [String] $FilePath, - [String[]] $ArgumentList = @(' '), - [Int] $Timeout = 0, - [Switch] $NoWait, - [Switch] $PassThru, - [String] $WorkingDir = (Get-Location).ProviderPath - ) - - trap { - Write-LogError $_.Exception.Message - return $null - } - - Write-Log "Starting program: $FilePath $ArgumentList" - - $ProcessStartInfo = New-Object System.Diagnostics.ProcessStartInfo - $ProcessStartInfo.FileName = $FilePath - $ProcessStartInfo.Arguments = $ArgumentList - $ProcessStartInfo.CreateNoWindow = $true - $ProcessStartInfo.RedirectStandardOutput = $true - $ProcessStartInfo.RedirectStandardError = $true - $ProcessStartInfo.UseShellExecute = $false - $ProcessStartInfo.WorkingDirectory = $WorkingDir - - $Process = [System.Diagnostics.Process]::Start($ProcessStartInfo) - - if ($NoWait) { - if ($PassThru) { - return $Process - } - else { - return $null - } - } - else { - if ($Timeout -eq 0) { - $Process.WaitForExit() - } - else { - $Process.WaitForExit($Timeout) - } - } - - $ProcessResult = New-Object PSObject | - Add-Member -Name "ExitCode" -MemberType NoteProperty -Value $Process.ExitCode -PassThru | - Add-Member -Name "StdOut" -MemberType NoteProperty -Value $Process.StandardOutput.ReadToEnd() -PassThru | - Add-Member -Name "StdErr" -MemberType NoteProperty -Value $Process.StandardError.ReadToEnd() -PassThru - - $Process = $null - - Write-Log ( "STDOUT:`n{0}" -f $ProcessResult.StdOut ) - Write-Log ":STDOUT" - - Write-Log ( "STDERR:`n{0}" -f $ProcessResult.StdErr ) - Write-Log ":STDERR" - - Write-Log "Program has finished with exit code ($($ProcessResult.ExitCode))" - - if ($PassThru) { - return $ProcessResult - } - else { - return $null - } -} -New-Alias -Name Exec -Value Start-Program - - - -Function Backup-File { - param ( - [String] $Path - ) - - $BackupFile = "$Path.bak" - - if (-not [IO.File]::Exists($Path)) { - Write-LogError "Unable to backup file '$Path': file not exists." - return - } - - if ([IO.File]::Exists($BackupFile)) { - try { - [IO.File]::Delete($BackupFile) - } - catch { - Write-LogError "Unable to delete existing .bak file '$BackupFile'." - return - } - } - - Write-Log "Backing up file '$Path' to '$BackupFile'" - [IO.File]::Copy($Path, $BackupFile, $true) -} - - - -Function Install-Module { - param ( - [String] $InstallPath, - [String] $ModulePath, - [String] $ModuleName - ) - - if ($ModuleName -eq "") { - if ($ModulePath -eq "") { - Stop-Execution -ExitString "Don't know which module should be installed." - } - else { - $ModuleName = $ModulePath.Split("\")[-1] - } - } - - if ($InstallPath -eq "") { - Stop-Execution -ExitString "To install the module destination path must be provided." - } - else { - Write-Log "Installing the module to '$InstallPath'" - - $NewModulePath = [IO.Path]::Combine($InstallPath, $ModuleName) - if ([IO.Directory]::Exists($NewModulePath)) { - [IO.Directory]::Delete($NewModulePath, $true) - } - - Copy-Item -Path $ModulePath -Destination $InstallPath -Recurse -Force -ErrorAction Stop - - Update-PsModulePath -AddPath "$InstallPath" - } -} - - - -Function Register-Module { - param ( - [String] $ModulePath - ) - $ModuleRoot = Split-Path -Path $ModulePath -Parent - Write-Log "Registering the module at '$ModuleRoot'" - Update-PsModulePath -AddPath "$ModuleRoot" -} - - - -function Test-ModuleVersion { -<# -.SYNOPSIS -Test module version. - -.DESCRIPTION -Function specified module (current module by default), and compares it's version to version provided. -Returned values: -* -2 : error occured -* -1 : module's version is lower than one provided -* 0 : module's version is equal to one provided -* 1 : module's version is greater than one provided -#> - param ( - [String] $Name = "$__ModuleName", - [String] $Version - ) - - $ModuleVersion = (Get-Module -Name $Name -ListAvailable).Version - - if ($ModuleVersion -eq $null) { - Write-Log "Module '$Name' not found." - return -2 - } - - try { - $RequiredVersion = [System.Version]::Parse($Version) - } - catch { - Write-Log "'$Version' is not a correct version string." - return -2 - } - - $ModuleVersion.CompareTo($RequiredVersion) -} diff --git a/Deployment/WindowsPowerShell/Modules/CoreFunctions/include/Logger.ps1 b/Deployment/WindowsPowerShell/Modules/CoreFunctions/include/Logger.ps1 deleted file mode 100644 index 9bcb6b75..00000000 --- a/Deployment/WindowsPowerShell/Modules/CoreFunctions/include/Logger.ps1 +++ /dev/null @@ -1,137 +0,0 @@ -Function Initialize-Logger { - param ( - [String] $ModuleName = $__ModuleName, - [String] $LogPath = $__DefaultLogPath - ) - - if (-not ("log4net.LogManager" -as [type])) { - $FileStream = ([System.IO.FileInfo] (Get-Item "$__ModulePath\log4net.dll")).OpenRead() - - $AssemblyBytes = New-Object Byte[] $FileStream.Length - [Void] $FileStream.Read($AssemblyBytes, 0, $FileStream.Length) - - $FileStream.Close() - - [Void] [System.Reflection.Assembly]::Load($AssemblyBytes) - } - - [log4net.GlobalContext]::Properties["LogPath"] = $LogPath - [log4net.GlobalContext]::Properties["ModuleName"] = $ModuleName - - $script:__Logger = [log4net.LogManager]::GetLogger("PowerShell") - - $Log4NetConfig = New-Object System.IO.FileInfo("$__ModulePath\log4net.config") - - [log4net.Config.XmlConfigurator]::Configure($Log4NetConfig) - - $__Logger.info("Logger initialized. Log file: '$LogPath'`n") -} - - -Function Out-LogInfo { - param ( - [Parameter(ValueFromPipeline=$true)] - $InputObject, - [Switch] $EntireObject - ) - process { - if ($EntireObject) { - $__Logger.info("`n$(Out-String -InputObject $InputObject)") - } - else { - foreach ($Object in $InputObject) { - $__Logger.info((Out-String -InputObject $Object)) - } - } - } -} -New-Alias -Name Out-Log -Value Out-LogInfo -New-Alias -Name Write-Log -Value Out-LogInfo - - - -Function Out-LogWarning { - param ( - [Parameter(ValueFromPipeline=$true)] - $InputObject, - [Switch] $EntireObject - ) - process { - if ($EntireObject) { - $__Logger.warn("`n$(Out-String -InputObject $InputObject)") - } - else { - foreach ($Object in $InputObject) { - $__Logger.warn((Out-String -InputObject $Object)) - } - } - } -} -New-Alias -Name Write-LogWarning -Value Out-LogWarning - - - -Function Out-LogError { - param ( - [Parameter(ValueFromPipeline=$true)] - $InputObject, - [Switch] $EntireObject - ) - process { - if ($EntireObject) { - $__Logger.error("`n$(Out-String -InputObject $InputObject)") - } - else { - foreach ($Object in $InputObject) { - $__Logger.error((Out-String -InputObject $Object)) - } - } - } -} -New-Alias -Name Write-LogError -Value Out-LogError - - - -Function Out-LogFatal { - param ( - [Parameter(ValueFromPipeline=$true)] - $InputObject, - [Switch] $EntireObject - ) - process { - if ($EntireObject) { - $__Logger.fatal("`n$(Out-String -InputObject $InputObject)") - } - else { - foreach ($Object in $InputObject) { - $__Logger.fatal((Out-String -InputObject $Object)) - } - } - } -} -New-Alias -Name Write-LogFatal -Value Out-LogFatal - - - -Function Out-LogDebug { - param ( - [Parameter(ValueFromPipeline=$true)] - $InputObject, - [Switch] $EntireObject - ) - process { - if ($EntireObject) { - $__Logger.debug("`n$(Out-String -InputObject $InputObject)") - } - else { - foreach ($Object in $InputObject) { - $__Logger.debug((Out-String -InputObject $Object)) - } - } - } -} -New-Alias -Name Write-LogDebug -Value Out-LogDebug - - - -Initialize-Logger diff --git a/Deployment/WindowsPowerShell/Modules/CoreFunctions/include/Module.ps1 b/Deployment/WindowsPowerShell/Modules/CoreFunctions/include/Module.ps1 deleted file mode 100644 index e69de29b..00000000 diff --git a/Deployment/WindowsPowerShell/Modules/CoreFunctions/include/NotCoreFunctions.ps1 b/Deployment/WindowsPowerShell/Modules/CoreFunctions/include/NotCoreFunctions.ps1 deleted file mode 100644 index 62ac8bc0..00000000 --- a/Deployment/WindowsPowerShell/Modules/CoreFunctions/include/NotCoreFunctions.ps1 +++ /dev/null @@ -1,814 +0,0 @@ -Function Set-LocalUserPassword { - param ( - [String] $UserName, - [String] $Password, - [Switch] $Force - ) - - trap { Stop-Execution $_ } - - if ((Get-WmiObject Win32_UserAccount -Filter "LocalAccount = 'True' AND Name='$UserName'") -eq $null) { - throw "Unable to find local user account '$UserName'" - } - - if ($Force) { - Write-Log "Changing password for user '$UserName' to '*****'" # :) - ([ADSI] "WinNT://./$UserName").SetPassword($Password) | Out-Null - } - else { - Write-LogWarning "You are trying to change the password for the user '$UserName'. To do this please run the command again with -Force parameter." - } -} - - - -Function Set-AutoLogonCredentials { - param ( - [String] $DomainName, - [String] $UserName, - [String] $Password - ) - - $KeyName = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" - - if ($DomainName -ne "") { - $UserName = "$DomainName\$UserName" - } - - Write-Log "Setting AutoLogon credentials ..." - try { - [Microsoft.Win32.Registry]::SetValue($KeyName, "DefaultUserName", "$UserName", [Microsoft.Win32.RegistryValueKind]::String) - [Microsoft.Win32.Registry]::SetValue($KeyName, "DefaultPassword", "$Password", [Microsoft.Win32.RegistryValueKind]::String) - [Microsoft.Win32.Registry]::SetValue($KeyName, "AutoAdminLogon", "1", [Microsoft.Win32.RegistryValueKind]::String) - [Microsoft.Win32.Registry]::SetValue($KeyName, "ForceAutoLogon", "1", [Microsoft.Win32.RegistryValueKind]::String) - } - catch { - Write-LogError "FAILED" - return - } - - Write-Log "SUCCESS" -} - - - -Function Join-Domain { -<# -.SYNOPSIS -Executes "Join domain" action. -#> - param ( - [String] $DomainName, - [String] $UserName, - [String] $Password, - [Switch] $AllowRestart - ) - - $Credential = New-Credential -UserName "$DomainName\$UserName" -Password $Password - - # Add the computer to the domain - if (Test-ComputerName -DomainName $DomainName) { - #Stop-Execution -Success -ExitString "Computer already joined to domain '$DomainName'" - Write-LogWarning "Computer already joined to domain '$DomainName'" - } - else { - Write-Log "Joining computer to domain '$DomainName' ..." - - Add-Computer -DomainName $DomainName -Credential $Credential -Force -ErrorAction Stop - - if ($AllowRestart) { - Write-Log "Restarting computer ..." - Restart-Computer -Force - } - else { - #Stop-Execution -ExitCode 3010 -ExitString "Please restart the computer now." - Write-Log "Please restart the computer now." - } - } -} - - - -Function Expand-Template { - param ( - [String] $TemplateFile, - [String] $OutputFile, - [System.Collections.Hashtable] $ReplacementList, - [String] $Encoding = "Ascii" - ) - - if (-not [IO.File]::Exists($TemplateFile)) { - Write-Error "File '$TemplateFile' not exists" - return $null - } - - if ([IO.File]::Exists($OutputFile)) { - [IO.File]::Delete($OutputFile) - } - - Get-Content $TemplateFile -Encoding $Encoding | - ForEach-Object { - $Line = $_ - foreach ($Key in $ReplacementList.Keys) { - $Line = $Line.Replace("%_$($Key)_%", $ReplacementList[$Key]) - } - Add-Content -Path $OutputFile -Encoding $Encoding -Value $Line - } -} - - - -Function Add-WindowsFeatureWrapper { -<# -.SYNOPSIS -Wraps Install-WindowsFeature function. - -.DESCRIPTION -This function adds some logic to multiple feature installation. - -It fails if any of required features fails. - -It reports that reboot required if it is required, or restarts the computer. -#> - param ( - [Parameter(Mandatory=$true)] - [String[]] $Name, - [Switch] $IncludeManagementTools, - [Switch] $AllowRestart, - [Switch] $NotifyRestart - ) - - $RestartNeeded = $false - - foreach ($Feature in $Name) { - Write-Log "Installing feature '$Feature' ..." - $Action = Install-WindowsFeature ` - -Name $Feature ` - -IncludeManagementTools:$IncludeManagementTools ` - -ErrorAction Stop - - if ($Action.Success -eq $true) { - if ($Action.FeatureResult.RestartNeeded -eq $true) { - Write-LogWarning "Restart required" - $RestartNeeded = $true - } - Write-Log "Feature '$Feature' installed successfully" - } - else { - Stop-Execution "Failed to install feature '$Feature'" - } - } - - if ($RestartNeeded) { - Write-Log "Restart required to finish feature(s) installation." - if ($AllowRestart) { - Write-Log "Restarting computer ..." - Restart-Computer -Force - } - elseif ($NotifyRestart) { - Stop-Execution -ExitCode 3010 -ExitString "Please restart the computer now." - } - } -} - - - -Function Test-WmiReturnValue { -<# -.SYNOPSIS -Check the ReturnValue property of the object provided. - -.DESCRIPTION -This funciton checks if ReturnValue property is equal to 0. - -=== TODO === -If it is not, then funtion should try to provide desctiption for the error code based on the WMI object type. -WMI object type must be provided explicitely. -#> - param ( - [Parameter(ValueFromPipeline=$true,Mandatory=$true)] - $InputObject, - [String] $Type = "" - ) - - try { - $ReturnValue = $InputObject.ReturnValue - } - catch { - throw "Property 'ReturnValue' not found on this object" - } - - if ($ReturnValue -eq 0) { - Write-Log "WMI operation completed successfully" - } - else { - throw "Operation failed with status code = $ReturnValue" - } -} - - - -Function Set-NetworkAdapterConfiguration { -<# -.SYNOPSIS -Set network adapter configuration. - -.DESCRIPTION - - -.EXAMPLE -PS> Set-NetworkAdapterConfiguration -MACAddress aa:bb:cc:dd:ee:ff -Auto - -Convert "dynamic" parameters (DHCP) to "static" (manual) for network adapter with MAC address aa:bb:cc:dd:ee:ff - -.EXAMPLE -PS> Set-NetworkAdapterConfiguration -MACAddress aa:bb:cc:dd:ee:ff -DNSServer "192.168.0.1","192.168.0.2" - -Configure DNS servers list for network adapter with MAC address aa:bb:cc:dd:ee:ff - -#> - param ( - [String] $MACAddress = "", - - [Parameter(ParameterSetName="ManualConfig")] - [String] $IPAddress = "", - - [Parameter(ParameterSetName="ManualConfig")] - [String] $IPNetmask = "", - - [Parameter(ParameterSetName="ManualConfig")] - [String[]] $IPGateway = @(), - - [Parameter(ParameterSetName="ManualConfig")] - [String[]] $DNSServer = @(), - - [Parameter(ParameterSetName="ManualConfig")] - [Switch] $FirstAvailable, - - [String] $Name = "", - - [Parameter(ParameterSetName="AutoConfig",Mandatory=$true)] - [Switch] $Auto, - - [Parameter(ParameterSetName="AutoConfig")] - [Switch] $All - ) - - Write-Log "Configuring network adapter(s) ..." - - :SetIPAddress switch($PSCmdlet.ParameterSetName) { - "AutoConfig" { - Write-Log "'auto' mode" - - $IPv4RegExp = "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" - - if ($All -eq $true) { - $Filter = { $_.AdapterTypeId -eq 0 } - $Name = "" - } - else { - $Filter = { $_.MACAddress -eq $MACAddress } - } - - Get-WmiObject Win32_NetworkAdapter | - Where-Object $Filter | - ForEach-Object { - $NetworkAdapter = $_ - $AdapterConfig = Get-WmiObject Win32_NetworkAdapterConfiguration | - Where-Object { $_.Index -eq $NetworkAdapter.DeviceId } - - Write-Log "Configuring '$($NetworkAdapter.Name)' ..." - - for ($i = 0; $i -lt $AdapterConfig.IPAddress.Length; $i++) { - if ($AdapterConfig.IPAddress[$i] -match $IPv4RegExp) { - $IPAddress = $AdapterConfig.IPAddress[$i] - $IPNetmask = $AdapterConfig.IPSubnet[$i] - $IPGateway = $AdapterConfig.DefaultIPGateway - $DNSServer = $AdapterConfig.DNSServerSearchOrder - - Write-Log "Setting IP address ($IPAddress), netmask ($IPNetmask) ..." - $AdapterConfig.EnableStatic($IPAddress, $IPNetmask) | Out-Null - - Write-Log "Setting default gateways ($IPGateway) ..." - $AdapterConfig.SetGateways($IPGateway) | Out-Null - - Write-Log "Setting DNS servers ($DNSServer) ..." - $AdapterConfig.SetDNSServerSearchOrder($DNSServer) | Out-Null - } - } - - Write-Log "'$($NetworkAdapter.Name)' configured" - } - } - "ManualConfig" { - Write-Log "'manual' mode" - if ( $FirstAvailable ) { - Write-Log "Selecting first available network adapter ..." - $NetworkAdapter = Get-WmiObject Win32_NetworkAdapter | - Where-Object { $_.AdapterTypeId -eq 0 } | - Select-Object -First 1 - } - else { - $NetworkAdapter = Get-WmiObject Win32_NetworkAdapter | - Where-Object { $_.MACAddress -eq $MACAddress } - } - - if ( $NetworkAdapter -eq $null ) { - Write-LogError "Network adapter with MAC = '$MACAddress' not found." - return - } - - $AdapterConfig = Get-WmiObject Win32_NetworkAdapterConfiguration | - Where-Object { $_.Index -eq $NetworkAdapter.DeviceId } - - if (($IPAddress -ne "") -and ($IPNetmask -ne "")) { - Write-Log "Configuring IP address / netmask for '$($NetworkAdapter.Name)' ..." - - <# - for ($i = 0; $i -lt $AdapterConfig.IPAddress.Length; $i++) - { - if (($AdapterConfig.IPAddress[$i] -eq $IPAddress) -and ($AdapterConfig.IPSubnet[$i] -eq $IPNetmask)) - { - Write-Log "There is an adapter with required configuration." - break SetIPAddress - } - } - #> - Write-Log "Setting IP address $IPAddress, netmask $IPNetmask" - $AdapterConfig.EnableStatic("$IPAddress", "$IPNetmask") | Out-Null - - Write-Log "IP address configured." - } - - if ($IPGateway.Count -gt 0) { - Write-Log "Configuring IP gateway for '$($NetworkAdapter.Name)' ..." - - $AdapterConfig.SetGateways($IPGateway) | Out-Null - - Write-Log "IP gateway configured." - } - - if ($DNSServer.Count -gt 0) { - Write-Log "Configuring DNS server(s) for '$($NetworkAdapter.Name)' ..." - - $AdapterConfig.SetDNSServerSearchOrder($DNSServer) | Out-Null - - Write-Log "DNS configured." - } - } - } - - if ($Name -ne "") { - Write-Log "Changing adapter name '$($NetworkAdapter.NetConnectionId)' --> '$Name'" - $NetworkAdapter.NetConnectionId = "$Name" - $NetworkAdapter.Put() | Out-Null - } -} - - - -Function Show-EthernetNetworkAdapters { - Get-WmiObject Win32_NetworkAdapter -Filter "PhysicalAdapter = 'True' AND AdapterTypeId = '0'" | - Select-Object 'Index','MACAddress','NetConnectionId' -} - - - -Function Test-ComputerName { -<# -.SYNOPSIS -Test if computer name is set, and the computer belongs to specified domain / workgroup. - -.DESCRIPTION -Function tests the following conditions: -* the computer name is equal to the provided one -* the computer is a part of domain -* the computer belongs to the specified domain -* the computer belongs to the specified workgroup - -Multiple checks are logically ANDed. -#> - [CmdletBinding()] - param ( - [String] $ComputerName, - [String] $DomainName, - [String] $WorkgroupName, - [Switch] $PartOfDomain - ) - process { - $ComputerSystem = Get-WmiObject Win32_ComputerSystem - - if (($ComputerName -ne "") -and ($ComputerSystem.Name -ne "$ComputerName")) { - Write-Error "ComputerName is not equal to '$ComputerName'" - return $false - } - - if (($DomainName -ne "") -and ($ComputerSystem.Domain -ne "$DomainName")) { - Write-Error "DomainName is not equal to '$DomainName'" - return $false - } - - if (($WorkgroupName -ne "") -and ($ComputerSystem.Workgroup -ne "$WorkgroupName")) { - Write-Error "WorkgroupName is not equal to '$WorkgroupName'" - return $false - } - - if (($PartOfDOmain -eq $true) -and ($ComputerSystem.PartOfDomain -eq $false)) { - Write-Error "Computer is not the part of any domain." - return $false - } - - return $true - } -} - - - -Function Set-ComputerName { - param ( - [String] $Name - ) - - - # Rename the computer - if ($Name -ne "") { - if (Test-ComputerName -ComputerName $Name) { - Stop-Execution -Success -ExitString "Computer name already configured" - } - else { - Write-Log "Renaming computer to '$Name'" - - Rename-Computer -NewName $NewName -Force -ErrorAction Stop - - Stop-Execution -ExitCode 3010 -ExitString "Please restart the computer now" - } - } -} - - - - -Function Resolve-LdapDnsName { - param ( - [String] $DomainName - ) - - Resolve-DNSName -Type "SRV" -Name "_ldap._tcp.dc._msdcs.$DomainName" | - Where-Object { $_.Type -eq "A" } | - Select-Object -Property Name,IPAddress -} - - - -Function Wait-LdapServerAvailable { - param ( - [String] $DomainName, - [Int] $PingSeqCountThreshold = 10, - [Int] $PingSeqPerHostThreshold = 5 - ) - - $LdapServerList = @( Resolve-LdapDnsName $DomainName ) - Write-Log @( "Ldap server list:", ( $LdapServerList | Out-String ) ) - - :MainLoop foreach ($LdapServer in $LdapServerList) { - $PingSeqCount = 0 - $PingSeqPerHost = 0 - while ($PingSeqPerHost -lt $PingSeqPerHostThreshold) { - if (Test-Connection -ComputerName $LdapServer.IpAddress -Count 1 -Quiet) { - Write-Log "Ping '$($LdapServer.Name)' OK" - $PingSeqCount++ - } - else { - Write-Log "Ping '$($LdapServer.Name)' FAILED" - $PingSeqCount = 0 - $PingSeqPerHost++ - } - - if ($PingSeqCount -ge $PingSeqCountThreshold) { - Write-Log "Returning true" - return $true - } - - Start-Sleep -Seconds 1 - } - } - - Write-Log "Returning false" - return $false -} - - - -Function Get-ConfigDriveObject { - [CmdletBinding()] - param ( - [Parameter(ParameterSetName="MetaData")] - [Switch] $MetaData, - - [Parameter(ParameterSetName="UserData")] - [Switch] $UserData, - - [Parameter(ParameterSetName="CustomObject")] - [String] $CustomObject, - - [String] $Path = "openstack/latest" - ) - - $ConfigDrivePrefix = "http://169.254.169.154/$Path" - - try { - switch($PSCmdlet.ParameterSetName) { - "MetaData" { - $ConfigDriveObjectUrl = "$ConfigDrivePrefix/meta_data.json" - $MetaData = Invoke-WebRequest $ConfigDriveObjectUrl - ConvertFrom-Json $MetaData.Content - } - "UserData" { - $ConfigDriveObjectUrl = "$ConfigDrivePrefix/user_data" - $UserData = Invoke-WebRequest $ConfigDriveObjectUrl - $UserData.Content - } - "CustomObject" { - $ConfigDriveObjectUrl = "$ConfigDrivePrefix/$CustomObject" - $CustomObject = Invoke-WebRequest $ConfigDriveObjectUrl - $CustomObject.Content - } - } - } - catch { - Write-Error "Unable to retrieve object from 'ConfigDriveObjectUrl'" - return $null - } -} - - - -Function Update-AgentConfig { - param ( - [String] $RootPath = "C:\Keero\Agent" - ) - - try { - $MetaData = Get-ConfigDriveObject -MetaData -ErrorAction Stop - if ($MetaData.meta -ne $null) { - Stop-Service "Keero Agent" -Force - Expand-Template -TemplateFile "$RootPath\WindowsAgent.exe.config.template" -OutputFile "$RootPath\WindowsAgent.exe.config" -ReplacementList $MetaData.meta - Start-Service "Keero Agent" - } - } - catch { - Write-LogError "Failed to update agent configuration" - } -} - - - -Function Update-PsModulePath { - param ( - [String] $AddPath = "" - ) - - $NewPsModulePath = ( - @([Environment]::GetEnvironmentVariable("PsModulePath", [EnvironmentVariableTarget]::Machine) -split ";") + @($AddPath) ` - | Select-Object -Unique - ) -join ';' - - [Environment]::SetEnvironmentVariable("PsModulePath", $NewPsModulePath, [EnvironmentVariableTarget]::Machine) - - Invoke-WMSettingsChange -} - - - -Function Get-ModuleHelp { - param ( - [String] $ModuleName = $__ModuleName, - [String] $Path = "", - [Switch] $File, - [Int] $Width = 80 - ) - - $sb = { - $Module = Get-Module $ModuleName - - "`n" - "Module: $($Module.Name)" - "Module version: $($Module.Version)" - "`n" - "{0} Module Description {0}" -f ('=' * 30) - "`n" - - Get-Help "about_$($Module.Name)" | Out-String -Width $Width - - "{0} Exported Functions {0}" -f ('=' * 30) - "`n" - - foreach ($CommandName in $Module.ExportedCommands.Keys) { - '-' * 80 - Get-Help -Name $CommandName -Detailed | Out-String -Width $Width - } - } - - if (($File) -and ($Path -eq "")) { - $Path = [IO.Path]::GetTempFileName() - } - - if ($Path -ne "") { - & $sb | Out-File -FilePath $Path -Force - } - else { - & $sb | Out-Default - } - - if ($File) { - notepad.exe "$Path" - } -} - - - -Function New-ModuleTemplate { - param ( - [Parameter(Mandatory=$true)] - [String] $Name, - - [String] $Path = "$($Env:USERPROFILE)\Documents\WindowsPowerShell\Modules", - - [Switch] $Force - ) - if ([IO.Directory]::Exists("$Path\$Name")) { - if ($Force) { - [IO.Directory]::Delete("$Path\$Name", $true) - } - else { - Write-Error "Folder '$Path\$Name' already exists. Remove it manually or specify -Force switch." - return - } - } - - - [IO.Directory]::CreateDirectory("$Path\$Name") - [IO.Directory]::CreateDirectory("$Path\$Name\en-US") - [IO.Directory]::CreateDirectory("$Path\$Name\include") - - - Set-Content -Path "$Path\$Name\en-US\about_$Name.help.txt" -Value @' -'@ - - - Set-Content -Path "$Path\$Name\Config.ps1" -Value @' -$script:__ModulePath = $PsScriptRoot -$script:__ModuleName = $PsScriptRoot.Split("\")[-1] -$script:__DefaultLogPath = [IO.Path]::Combine([IO.Path]::GetTempPath(), "PowerShell_$__ModuleName.log") - -$global:__StopExecutionExitsSession__ = $false -'@ - - - Set-Content -Path "$Path\$Name\$Name.psm1" -Value @' -# Import config first -. "$PsScriptRoot\Config.ps1" - -# Import functions from 'Include' subfolder -Get-ChildItem "$PsScriptRoot\Include" -Filter "*.ps1" | - ForEach-Object { - . "$($_.FullName)" - } - -Export-ModuleMember -Function * -Alias * - -Initialize-Logger -ModuleName $__ModuleName -LogPath $__DefaultLogPath - -Write-Log "Module loaded from '$PsScriptRoot'" -'@ - - - New-ModuleManifest ` - -Path "$Path\$Name\$Name.psd1" ` - -ModuleToProcess "$Name.psm1" ` - -RequiredModules "CoreFunctions" - -} - - - -function New-SqlServerConnection { - param ( - [String] $ServerName, - [String] $UserName = '', - [String] $Password = '', - $Credentials, - [Switch] $SqlAuth - ) - - if ($Credentials -eq $null) { - if ($UserName -eq '') { - throw "User name must be provided in order to create credentials object!" - } - - $Credentials = New-Credential -UserName $UserName -Password $Password - } - - $Server = New-Object ` - -TypeName Microsoft.SqlServer.Management.Smo.Server ` - -ArgumentList $ServerName - - $LoginName = $Credentials.UserName -replace("^\\", "") - - try { - if ($SqlAuth) { - $Server.ConnectionContext.set_LoginSecure($false) - $Server.ConnectionContext.set_Login($LoginName) - $Server.ConnectionContext.set_SecurePassword($Credentials.Password) - } - else { - throw "Not implemented!" - } - } - catch { - return $null - } - - $Server -} - - - -function Import-SqlServerAssemblies { -<# -.SYNOPSIS -Import assemblies required to work with Sql Server instance from PowerShell - -.DESCRIPTION -Possible assembly list: - "Microsoft.SqlServer.Management.Common" - "Microsoft.SqlServer.Smo" - "Microsoft.SqlServer.Dmf" - "Microsoft.SqlServer.Instapi" - "Microsoft.SqlServer.SqlWmiManagement" - "Microsoft.SqlServer.ConnectionInfo" - "Microsoft.SqlServer.SmoExtended" - "Microsoft.SqlServer.SqlTDiagM" - "Microsoft.SqlServer.SString" - "Microsoft.SqlServer.Management.RegisteredServers" - "Microsoft.SqlServer.Management.Sdk.Sfc" - "Microsoft.SqlServer.SqlEnum" - "Microsoft.SqlServer.RegSvrEnum" - "Microsoft.SqlServer.WmiEnum" - "Microsoft.SqlServer.ServiceBrokerEnum" - "Microsoft.SqlServer.ConnectionInfoExtended" - "Microsoft.SqlServer.Management.Collector" - "Microsoft.SqlServer.Management.CollectorEnum" - "Microsoft.SqlServer.Management.Dac" - "Microsoft.SqlServer.Management.DacEnum" - "Microsoft.SqlServer.Management.Utility" - -.LINKS -http://msdn.microsoft.com/en-us/library/cc281962%28v=sql.105%29.aspx -#> - $AssemblyList = @( - "Microsoft.SqlServer.Smo" - "Microsoft.SqlServer.SmoExtended" - ) - - foreach ($asm in $AssemblyList) { - [System.Reflection.Assembly]::LoadWithPartialName($asm) | Out-Null - } -} - - - -function Import-SqlServerProvider { - $SqlPsReg="HKLM:\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.SqlServer.Management.PowerShell.sqlps" - - if (Get-ChildItem $SqlPsReg -ErrorAction "SilentlyContinue") { - throw "SQL Server Provider for Windows PowerShell is not installed." - } - else { - $Item = Get-ItemProperty $SqlPsReg - $SqlPsPath = [System.IO.Path]::GetDirectoryName($Item.Path) - } - - # - # Set mandatory variables for the SQL Server provider - # - $global:SqlServerMaximumChildItems = 0 - $global:SqlServerConnectionTimeout = 30 - $global:SqlServerIncludeSystemObjects = $false - $global:SqlServerMaximumTabCompletion = 1000 - - # - # Load the snapins, type data, format data - # - Push-Location - Set-Location $sqlpsPath - - Add-PSSnapin SqlServerCmdletSnapin100 - Add-PSSnapin SqlServerProviderSnapin100 - - Update-TypeData -PrependPath SQLProvider.Types.ps1xml - Update-FormatData -PrependPath SQLProvider.Format.ps1xml - - Pop-Location -} - diff --git a/Deployment/WindowsPowerShell/Modules/CoreFunctions/include/SqlFunctions.ps1 b/Deployment/WindowsPowerShell/Modules/CoreFunctions/include/SqlFunctions.ps1 deleted file mode 100644 index 5f282702..00000000 --- a/Deployment/WindowsPowerShell/Modules/CoreFunctions/include/SqlFunctions.ps1 +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/Deployment/WindowsPowerShell/Modules/CoreFunctions/include/Zip.ps1 b/Deployment/WindowsPowerShell/Modules/CoreFunctions/include/Zip.ps1 deleted file mode 100644 index 0980da8b..00000000 --- a/Deployment/WindowsPowerShell/Modules/CoreFunctions/include/Zip.ps1 +++ /dev/null @@ -1,69 +0,0 @@ -[Void] [System.Reflection.Assembly]::LoadFrom("$__ModulePath\Ionic.Zip.dll") - - -Function Compress-Folder { -<# -#> - [CmdLetBinding()] - param ( - [Parameter(Mandatory=$true)] - [String] $Path, - - [String] $ZipFile = "", - - [Switch] $TempFile, - - [Switch] $ContentOnly - ) - - if (-not [IO.Directory]::Exists($Path)) { - Write-LogError "Directory '$Path' not found." - return - } - - if ($TempFile) { - $ZipFile = [IO.Path]::GetTempFileName() - } - - if ($ZipFile -eq "") { - $ZipFile = "$Path.zip" - } - - if ([IO.File]::Exists($ZipFile)) { - [IO.File]::Delete($ZipFile) - } - - $zip = New-Object Ionic.Zip.ZipFile - if ($ContentOnly) { - [Void] $zip.AddDirectory($Path) - } - else { - [Void] $zip.AddDirectory($Path, (Split-Path -Path $Path -Leaf)) - } - $zip.Save($ZipFile) - $zip.Dispose() - - return $ZipFile -} - - -Function Expand-Zip { -<# -#> - [CmdletBinding()] - param ( - [Parameter(Mandatory=$true)] - [String] $Path, - - [String] $Destination - ) - - if (-not [IO.File]::Exists($Path)) { - Write-LogError "File not found '$Path'" - return - } - - $zip = [Ionic.Zip.ZipFile]::Read($Path) - $zip.ExtractAll($Destination, [Ionic.Zip.ExtractExistingFileAction]::OverwriteSilently) - $zip.Dispose() -} diff --git a/Deployment/WindowsPowerShell/Modules/CoreFunctions/log4net.config b/Deployment/WindowsPowerShell/Modules/CoreFunctions/log4net.config deleted file mode 100644 index 1b0b20bc..00000000 --- a/Deployment/WindowsPowerShell/Modules/CoreFunctions/log4net.config +++ /dev/null @@ -1,42 +0,0 @@ -<log4net> - <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender" > - <param name="File" type="log4net.Util.PatternString" value="%property{LogPath}" /> - <param name="AppendToFile" value="true" /> - <param name="RollingStyle" value="Size" /> - <param name="MaxSizeRollBackups" value="100" /> - <param name="MaximumFileSize" value="1024KB" /> - <param name="StaticLogFileName" value="true" /> - <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> - <layout type="log4net.Layout.PatternLayout"> - <param name="ConversionPattern" value="%date [%-5level] [%property{ModuleName}] %message" /> - </layout> - </appender> - - <appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender"> - <mapping> - <level value="error" /> - <foreColor value="Red, HighIntensity" /> - </mapping> - <mapping> - <level value="warn" /> - <foreColor value="Yellow, HighIntensity" /> - </mapping> - <mapping> - <level value="info" /> - <foreColor value="Green, HighIntensity" /> - </mapping> - <layout type="log4net.Layout.PatternLayout"> - <conversionPattern value="%date [%-5level] [%property{ModuleName}] %message" /> - </layout> - </appender> - - <!--root> - <level value="info" /> - </root--> - - <logger name="PowerShell" additivity="false"> - <!--level value="info" /--> - <appender-ref ref="ColoredConsoleAppender" /> - <appender-ref ref="RollingFileAppender" /> - </logger> -</log4net> \ No newline at end of file diff --git a/Deployment/WindowsPowerShell/Modules/CoreFunctions/log4net.dll b/Deployment/WindowsPowerShell/Modules/CoreFunctions/log4net.dll deleted file mode 100644 index 1e66c82a..00000000 Binary files a/Deployment/WindowsPowerShell/Modules/CoreFunctions/log4net.dll and /dev/null differ diff --git a/Deployment/cloudbase-init/config/cloudbase-init.conf b/Deployment/cloudbase-init/config/cloudbase-init.conf deleted file mode 100644 index 0b167a0c..00000000 --- a/Deployment/cloudbase-init/config/cloudbase-init.conf +++ /dev/null @@ -1,11 +0,0 @@ -[DEFAULT] -username=Admin -groups=Administrators -inject_user_password=false -network_adapters= -config_drive_raw_hdd=false -config_drive_cdrom=false -verbose=true -logdir=C:\Program Files (x86)\Cloudbase Solutions\Cloudbase-Init\log\ -logfile=cloudbase-init.log -plugins=cloudbaseinit.plugins.windows.userdata.UserDataPlugin \ No newline at end of file diff --git a/Deployment/cloudbase-init/plugins/setagentconfig.py b/Deployment/cloudbase-init/plugins/setagentconfig.py deleted file mode 100644 index 25f93ced..00000000 --- a/Deployment/cloudbase-init/plugins/setagentconfig.py +++ /dev/null @@ -1,37 +0,0 @@ -import codecs - -from cloudbaseinit.osutils.factory import * -from cloudbaseinit.plugins.base import * -from cloudbaseinit.openstack.common import log as logging - -opts = [ - cfg.StrOpt('agent_config_file', default='C:\\Keero\\Agent\\WindowsAgent.exe.config', help='') -] - -CONF = cfg.CONF -CONF.register_opts(opts) - -LOG = logging.getLogger(__name__) - - -class SetHostNamePlugin(BasePlugin): - def execute(self, service): - meta_data = service.get_meta_data('openstack') - if 'meta' not in meta_data: - LOG.debug("Section 'meta' not found in metadata") - return False - - if 'agent_config_xml' not in meta_data['meta']: - LOG.debug("Config for agent not found in metadata section") - return False - - try: - configFile=codecs.open(CONF.agent_config_file, encoding='utf-8', mode='w+') - configFile.write(meta_data['meta']['agent_config_xml']) - configFile.close() - except: - LOG.error("Unable to update agent file.") - return False - - return True - diff --git a/Deployment/cloudbase-init/plugins/sethostname.py b/Deployment/cloudbase-init/plugins/sethostname.py deleted file mode 100644 index 9aa2e8d2..00000000 --- a/Deployment/cloudbase-init/plugins/sethostname.py +++ /dev/null @@ -1,20 +0,0 @@ - -from cloudbaseinit.osutils.factory import * -from cloudbaseinit.plugins.base import * -from cloudbaseinit.openstack.common import log as logging - -LOG = logging.getLogger(__name__) - - -class SetHostNamePlugin(BasePlugin): - def execute(self, service): - meta_data = service.get_meta_data('openstack') - if 'name' not in meta_data: - LOG.debug('Name not found in metadata') - return False - - osutils = OSUtilsFactory().get_os_utils() - - new_host_name = meta_data['name'].replace('.', '-') - return osutils.set_host_name(new_host_name) - diff --git a/Deployment/cloudbase-init/plugins/userdata.py b/Deployment/cloudbase-init/plugins/userdata.py deleted file mode 100644 index 076b58a7..00000000 --- a/Deployment/cloudbase-init/plugins/userdata.py +++ /dev/null @@ -1,119 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 Cloudbase Solutions Srl -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import re -import tempfile -import uuid -import email -import tempfile -import os -import errno - -from cloudbaseinit.openstack.common import cfg -from cloudbaseinit.openstack.common import log as logging -from cloudbaseinit.osutils.factory import * -from cloudbaseinit.plugins.base import * - -LOG = logging.getLogger(__name__) - -opts = [ - cfg.StrOpt('user_data_folder', default='cloud-data', - help='Specifies a folder to store multipart data files.'), - ] - -CONF = cfg.CONF -CONF.register_opts(opts) - -class UserDataPlugin(): - def __init__(self, cfg=CONF): - self.cfg = cfg - self.msg = None - return - - def execute(self, service): - user_data = service.get_user_data('openstack') - if not user_data: - return False - - LOG.debug('User data content:\n%s' % user_data) - - if user_data.startswith('Content-Type: multipart'): - for part in self.parse_MIME(user_data): - self.process_part(part) - else: - self.handle(user_data) - return - - def process_part(self, part): - if part.get_filename() == 'cfn-userdata': - self.handle(part.get_payload()) - return - - def parse_MIME(self, user_data): - folder = self.cfg.user_data_folder - self.create_folder(folder) - - self.msg = email.message_from_string(user_data) - return self.msg.walk() - - - def create_folder(self, folder): - try: - os.mkdir(folder) - except os.OSError, e: - if e.errno != errno.EEXIST: - raise e - return - - def handle(self, user_data): - - osutils = OSUtilsFactory().get_os_utils() - - target_path = os.path.join(tempfile.gettempdir(), str(uuid.uuid4())) - if re.search(r'^rem cmd\s', user_data, re.I): - target_path += '.cmd' - args = [target_path] - shell = True - elif re.search(r'^#!', user_data, re.I): - target_path += '.sh' - args = ['bash.exe', target_path] - shell = False - elif re.search(r'^#ps1\s', user_data, re.I): - target_path += '.ps1' - args = ['powershell.exe', '-ExecutionPolicy', 'RemoteSigned', - '-NonInteractive', target_path] - shell = False - else: - # Unsupported - LOG.warning('Unsupported user_data format') - return False - - try: - with open(target_path, 'wb') as f: - f.write(user_data) - (out, err, ret_val) = osutils.execute_process(args, shell) - - LOG.info('User_data script ended with return code: %d' % ret_val) - LOG.debug('User_data stdout:\n%s' % out) - LOG.debug('User_data stderr:\n%s' % err) - except Exception, ex: - LOG.warning('An error occurred during user_data execution: \'%s\'' % ex) - finally: - if os.path.exists(target_path): - os.remove(target_path) - - return False - diff --git a/Deployment/cloudbase-init/userdata/Sample.ps1 b/Deployment/cloudbase-init/userdata/Sample.ps1 deleted file mode 100644 index 878106cd..00000000 --- a/Deployment/cloudbase-init/userdata/Sample.ps1 +++ /dev/null @@ -1,24 +0,0 @@ -Import-Module CoreFunctions - -$ModuleBase = "C:\Keero\Modules" - - -$NewModule_Name = "ModuleName" -$NewModule_Base64 = @' -%BASE64_STRINGS% -'@ - - -$AgentConfig_Path = "C:\Keero\Agent\WindowsAgent.exe.config" -$AgentConfig_Base64 = @' -%AGENT_CONFIG_BASE64% -'@ - - -ConvertFrom-Base64String -Base64String $NewModule_Base64 -Path "$ModuleBase\$NewModule_Name.zip" -Remove-Item -Path "$ModuleBase\$NewModule_Name" -Recurse -Force -Expand-Zip -Path "$ModuleBase\$NewModule_Name.zip" -Destination "$ModuleBase\$NewModule_Name" - - -Remove-Item -Path $AgentConfig_Path -Force -ConvertFrom-Base64String -Base64String $NewModule_Base64 -Path $AgentConfig_Path diff --git a/Deployment/devstack-scripts/compute/devstack.localrc b/Deployment/devstack-scripts/compute/devstack.localrc deleted file mode 100644 index 6088490b..00000000 --- a/Deployment/devstack-scripts/compute/devstack.localrc +++ /dev/null @@ -1,51 +0,0 @@ -# Devstack's config file for COMPUTE intallation - - -lab_id=102 -lab_password=swordfish -lab_controller=172.18.124.100 - - -SERVICE_HOST=$lab_controller -HOST_IP=172.18.124.${lab_id} -MULTI_HOST=1 - - -FLAT_INTERFACE=eth1 -#PUBLIC_INTERFACE=eth0.261 - - -FIXED_RANGE=192.168.102.0/24 -FIXED_NETWORK_SIZE=254 -FLOATING_RANGE=172.18.124.228/27 - - -MYSQL_HOST=$lab_controller -RABBIT_HOST=$lab_controller -GLANCE_HOSTPORT=$lab_controller:9292 -KEYSTONE_AUTH_HOST=$lab_controller -KEYSTONE_SERVICE_HOST=$lab_controller - - -VNCSERVER_LISTEN=$HOST_IP -VNCSERVER_PROXYCLIENT_ADDRESS=$HOST_IP - - -ADMIN_PASSWORD=$lab_password -MYSQL_PASSWORD=$lab_password -RABBIT_PASSWORD=$lab_password -SERVICE_PASSWORD=$lab_password -SERVICE_TOKEN=tokentoken - - -ENABLED_SERVICES=n-cpu,n-net,n-api,n-vol,n-novnc - - -SCREEN_LOGDIR=/opt/stack/log/ -LOGFILE=$SCREEN_LOGDIR/stack.sh.log - - -API_RATE_LIMIT=False - - -EXTRA_OPTS=(force_config_drive=true libvirt_images_type=qcow2 force_raw_images=false sql_connection=mysql://root:${MYSQL_PASSWORD}@${MYSQL_HOST}/nova?charset=utf8) diff --git a/Deployment/devstack-scripts/controller/devstack.localrc b/Deployment/devstack-scripts/controller/devstack.localrc deleted file mode 100644 index 23513cb7..00000000 --- a/Deployment/devstack-scripts/controller/devstack.localrc +++ /dev/null @@ -1,45 +0,0 @@ -# Devstack's localrc for CONTROLLER installation - - -lab_id=100 -lab_password=swordfish - - -HOST_IP=172.18.124.${lab_id} - - -FLAT_INTERFACE=eth1 -#PUBLIC_INTERFACE=eth0.261 - - -FIXED_RANGE=192.168.102.0/24 -FIXED_NETWORK_SIZE=254 -PUBLIC_RANGE=172.18.124.228/27 - - -ADMIN_PASSWORD=$lab_password -MYSQL_PASSWORD=$lab_password -RABBIT_PASSWORD=$lab_password -SERVICE_PASSWORD=$lab_password -SERVICE_TOKEN=tokentoken - - -disable_service n-cpu -disable_service n-vol - - -ENABLED_SERVICES+=,heat,h-api,h-api-cfn,h-api-cw,h-eng -ENABLED_SERVICES+=,conductor,portas - - -SCREEN_LOGDIR=/opt/stack/log/ -LOGFILE=$SCREEN_LOGDIR/stack.sh.log - - -API_RATE_LIMIT=False - - -MULTI_HOST=1 - - -EXTRA_OPTS=(force_config_drive=true libvirt_images_type=qcow2 force_raw_images=false) diff --git a/Deployment/devstack-scripts/devstack.standalone.localrc b/Deployment/devstack-scripts/devstack.standalone.localrc deleted file mode 100644 index 3295cdf9..00000000 --- a/Deployment/devstack-scripts/devstack.standalone.localrc +++ /dev/null @@ -1,28 +0,0 @@ -lab_id=101 -lab_password=swordfish - -HOST_IP=172.18.124.${lab_id} -#PUBLIC_INTERFACE=eth1 - -FIXED_RANGE=10.0.${lab_id}.0/24 -NETWORK_GATEWAY=10.0.${lab_id}.1 - -#PUBLIC_INTERFACE=eth0 -FLAT_INTERFACE=eth1 - -ADMIN_PASSWORD=$lab_password -MYSQL_PASSWORD=$lab_password -RABBIT_PASSWORD=$lab_password -SERVICE_PASSWORD=$lab_password -SERVICE_TOKEN=tokentoken -ENABLED_SERVICES+=,heat,h-api,h-api-cfn,h-api-cw,h-eng -ENABLED_SERVICES+=,conductor,portas - -LOGFILE=/opt/stack/devstack/stack.sh.log -SCREEN_LOGDIR=/opt/stack/log/ -#SCREEN_LOGDIR=/dev/null - -API_RATE_LIMIT=False - -EXTRA_OPTS=(force_config_drive=true libvirt_images_type=qcow2 force_raw_images=false) - diff --git a/Deployment/devstack-scripts/functions.sh b/Deployment/devstack-scripts/functions.sh deleted file mode 100644 index b99ce7dc..00000000 --- a/Deployment/devstack-scripts/functions.sh +++ /dev/null @@ -1,148 +0,0 @@ -#!/bin/bash - - -# Checks an environment variable is not set or has length 0 OR if the -# exit code is non-zero and prints "message" and exits -# NOTE: env-var is the variable name without a '$' -# die_if_not_set env-var "message" -function die_if_not_set() { - local exitcode=$? - set +o xtrace - local evar=$1; shift - if ! is_set $evar || [ $exitcode != 0 ]; then - if [[ -z "$1" ]] ; then - die "Env var '$evar' is not set!" - else - die $@ - fi - fi -} - - - -function restart_service { - while [[ -n "$1" ]] ; do - _echo "Restarting service '$1' ..." - sudo service $1 restart - shift 1 - done -} - - - -function move_mysql_data_to_ramdrive { - # Moving MySQL database to tmpfs - #------------------------------- - if [[ $(trueorfalse True $MYSQL_DB_TMPFS) = "True" ]] ; then - die_if_not_set MYSQL_DB_TMPFS_SIZE - mount_dir=/var/lib/mysql - sudo -s << EOF -echo "Stopping MySQL Server" -service mysql stop - -umount $mount_dir -mount -t tmpfs -o size=$MYSQL_DB_TMPFS_SIZE tmpfs $mount_dir -chmod 700 $mount_dir -chown mysql:mysql $mount_dir - -mysql_install_db - -/usr/bin/mysqld_safe --skip-grant-tables & -sleep 5 -EOF - - sudo mysql << EOF -FLUSH PRIVILEGES; -SET PASSWORD FOR 'root'@'localhost' = PASSWORD('swordfish'); -SET PASSWORD FOR 'root'@'127.0.0.1' = PASSWORD('swordfish'); -EOF - - sudo -s << EOF -killall mysqld -sleep 5 - -echo "Starting MySQL Server" -service mysql start -EOF - else - _echo "MYSQL_DB_TMPFS = '$MYSQL_DB_TMPFS'" - fi - #------------------------------- -} - - -function move_nova_cache_to_ramdrive { - # Moving nova images cache to tmpfs - #---------------------------------- - if [[ $(trueorfalse True $NOVA_CACHE_TMPFS) = "True" ]] ; then - die_if_not_set NOVA_CACHE_TMPFS_SIZE - mount_dir=/opt/stack/data/nova/instances - sudo -s << EOF -umount $mount_dir -mount -t tmpfs -o size=$NOVA_CACHE_TMPFS_SIZE tmpfs $mount_dir -chmod 775 $mount_dir -chown stack:stack $mount_dir -EOF - else - _echo "NOVA_CACHE_TMPFS = '$NOVA_CACHE_TMPFS'" - fi - #---------------------------------- -} - - -function check_if_folder_exists { - if [[ ! -d "$1" ]] ; then - _echo "Folder '$1' not exists!" - return 1 - fi - return 0 -} - - -function validate_install_mode { - case $INSTALL_MODE in - 'standalone') - check_if_folder_exists "$SCRIPTS_DIR/standalone" || exit - ;; - 'multihost') - check_if_folder_exists "$SCRIPTS_DIR/controller" || exit - check_if_folder_exists "$SCRIPTS_DIR/compute" || exit - ;; - 'controller') - check_if_folder_exists "$SCRIPTS_DIR/controller" || exit - ;; - 'compute') - check_if_folder_exists "$SCRIPTS_DIR/compute" || exit - ;; - *) - _echo "Wrong install mode '$INSTALL_MODE'" - exit - ;; - esac -} - - -function update_devstack_localrc { - local $__install_mode=$1 - - [[ -z "$__install_mode" ]] \ - && die "Install mode for update_devstack_localrc not provided!" - - # Replacing devstack's localrc config - #------------------------------------ - devstack_localrc="$SCRIPTS_DIR/$__install_mode/devstack.localrc" - if [[ -f $devstack_localrc ]] ; then - rm -f "$DEVSTACK_DIR/localrc" - cp $devstack_localrc "$DEVSTACK_DIR/localrc" - else - _echo "File '$devstack_localrc' not found!" - fi - #------------------------------------ -} - - -function _echo { - echo "[$(hostname)] $@" -} - - diff --git a/Deployment/devstack-scripts/install-devstack.sh b/Deployment/devstack-scripts/install-devstack.sh deleted file mode 100644 index 7400b1f1..00000000 --- a/Deployment/devstack-scripts/install-devstack.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -SCRIPTS_DIR=$( cd $( dirname "$0" ) && pwd ) - -source $SCRIPTS_DIR/localrc - -groupadd stack -useradd -g stack -s /bin/bash -m stack - -echo 'stack ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/stack -chmod 0440 /etc/sudoers.d/stack - -mkdir -p $DEVSTACK_INSTALL_DIR -chmod stack:stack $DEVSTACK_INSTALL_DIR - -sudo -u stack << EOF -cd -rm -rf devstack -git clone git://github.com/openstack-dev/devstack.git -EOF - diff --git a/Deployment/devstack-scripts/localrc b/Deployment/devstack-scripts/localrc deleted file mode 100644 index 366c09de..00000000 --- a/Deployment/devstack-scripts/localrc +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -DEVSTACK_DIR=/home/stack/devstack -DEVSTACK_INSTALL_DIR=/opt/stack - -MYSQL_DB_TMPFS=true -MYSQL_DB_TMPFS_SIZE=128M - -NOVA_CACHE_TMPFS=true -NOVA_CACHE_TMPFS_SIZE=24G - -GLANCE_IMAGE_LIST="" -COMPUTE_NODE_LIST="172.18.124.102" - -#====================================== -if [[ -d "$DEVSTACK_DIR" ]] ; then - source $DEVSTACK_DIR/openrc admin admin -fi -source $SCRIPTS_DIR/functions.sh - diff --git a/Deployment/devstack-scripts/post-stack.sh b/Deployment/devstack-scripts/post-stack.sh deleted file mode 100644 index 7abe0bcd..00000000 --- a/Deployment/devstack-scripts/post-stack.sh +++ /dev/null @@ -1,109 +0,0 @@ -#!/bin/bash - -if [[ -z "$1" ]] ; then - SCRIPTS_DIR=$( cd $( dirname "$0" ) && pwd ) - source $SCRIPTS_DIR/localrc -fi - - -function glance_image_create { - local __image_path=$1 - - if [[ -z "$__image_path" ]] ; then - echo "Image path is missed!" - return - fi - - local __image_name=${__image_path##*/} - __image_name=${__image_name%.*} - - echo "Importing image '$__image_name' into Glance ..." - glance image-delete "$__image_name" - if [[ ^http =~ $__image_path]] ; then - glance image-create \ - --name "$__image_name" \ - --disk-format qcow2 \ - --container-format bare \ - --is-public true \ - --copy-from "$__image_path" - else - glance image-create \ - --name "$__image_name" \ - --disk-format qcow2 \ - --container-format bare \ - --is-public true \ - --file "$__image_path" - fi -} - -# Executing post-stack actions -#=============================================================================== - -if [[ ,$INSTALL_MODE, =~ ',standalone,compute,' ]] ; then - echo "Adding iptables rule to allow Internet access from instances..." - __iptables_rule="POSTROUTING -t nat -s '$FIXED_RANGE' ! -d '$FIXED_RANGE' -j MASQUERADE" - sudo iptables -C $__iptables_rule - if [[ $? == 0 ]] ; then - echo "Iptables rule already exists." - else - sudo iptables -A $__iptables_rule - fi -fi - - -if [[ $INSTALL_MODE == 'compute' ]] ; then - return -fi - - -if [[ -z "$(sudo rabbitmqctl list_users | grep keero)" ]] ; then - echo "Adding RabbitMQ 'keero' user" - sudo rabbitmqctl add_user keero keero -else - echo "User 'Keero' already exists." -fi - - -if [[ -z "$(sudo rabbitmq-plugins list -e | grep rabbitmq_management)" ]] ; then - echo "Enabling RabbitMQ management plugin" - sudo rabbitmq-plugins enable rabbitmq_management - - echo "Restarting RabbitMQ ..." - restart_service rabbitmq-server -else - echo "RabbitMQ management plugin already enabled." -fi - - -echo "* Removing nova flavors ..." -for id in $(nova flavor-list | awk '$2 ~ /[[:digit:]]/ {print $2}') ; do - echo "** Removing flavor '$id'" - nova flavor-delete $id -done - - -echo "* Creating new flavors ..." -nova flavor-create m1.small auto 768 40 1 -nova flavor-create m1.medium auto 1024 40 1 -nova flavor-create m1.large auto 1280 40 2 - - -echo "* Creating security group rules ..." -nova secgroup-add-rule default tcp 1 65535 0.0.0.0/0 -nova secgroup-add-rule default udp 1 65535 0.0.0.0/0 -nova secgroup-add-rule default icmp 0 8 0.0.0.0/0 - - -if [[ -z "$(nova keypair-list | grep keero_key)" ]] ; then - echo "Creating keypair 'keero_key' ..." - nova keypair-add keero_key -else - echo "Keypair 'keero_key' already exists" -fi - -#=============================================================================== - -for $image in $GLANCE_IMAGE_LIST ; do - glance_image_create "$image" -done - diff --git a/Deployment/devstack-scripts/post-unstack.sh b/Deployment/devstack-scripts/post-unstack.sh deleted file mode 100644 index 5e71c716..00000000 --- a/Deployment/devstack-scripts/post-unstack.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -if [[ -z "$1" ]] ; then - SCRIPTS_DIR=$( cd $( dirname "$0" ) && pwd ) - source $SCRIPTS_DIR/localrc -fi - - -#Remove certificates -echo "* Removing old certificate files" -for file in $(sudo find $DEVSTACK_DIR/accrc/ -type f -regex ".+.pem.*") ; do - echo "Removing file '$file'" - sudo rm -f "$file" -done - - -# Remove logs -echo "* Removing 'devstack' logs ..." -sudo rm -f /opt/stack/log/* - - -echo "* Removing 'apache2' logs ..." -for file in $(sudo find /var/log/apache2 -type f) ; do - echo "Removing file '$file'" - sudo rm -f "$file" -done - - -echo "* Stopping all VMs ..." -sudo killall kvm -sleep 2 - - -echo "* Unmounting ramdrive ..." -umount /opt/stack/data/nova/instances - diff --git a/Deployment/devstack-scripts/pre-stack.sh b/Deployment/devstack-scripts/pre-stack.sh deleted file mode 100644 index 7163cebb..00000000 --- a/Deployment/devstack-scripts/pre-stack.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash - -if [[ -z "$1" ]] ; then - SCRIPTS_DIR=$( cd $( dirname "$0" ) && pwd ) - source $SCRIPTS_DIR/localrc -fi - - -# Executing pre-stack actions -#=============================================================================== - -# Executing checks -#----------------- -die_if_not_set DEVSTACK_DIR -die_if_not_set MYSQL_DB_TMPFS_SIZE -die_if_not_set NOVA_CACHE_TMPFS_SIZE -#----------------- - - -if [[ ,$INSTALL_MODE, =~ ',standalone,multihost,controller,' ]] ; then - restart_service dbus rabbitmq-server -fi - - -if [[ ,$INSTALL_MODE, =~ ',standalone,multihost,controller,' ]] ; then - move_mysql_data_to_ramdrive -fi - - -# Devstack log folder -#-------------------- -sudo -s << EOF -mkdir -p $SCREEN_LOGDIR -chown stack:stack $SCREEN_LOGDIR -EOF -#-------------------- - - -case $INSTALL_MODE in - 'standalone') - update_devstack_localrc 'standalone' - ;; - 'multihost') - update_devstack_localrc 'controller' - ;; - 'controller') - update_devstack_localrc 'controller' - ;; - 'compute') - update_devstack_localrc 'compute' - ;; -esac - -#=============================================================================== - diff --git a/Deployment/devstack-scripts/pre-unstack.sh b/Deployment/devstack-scripts/pre-unstack.sh deleted file mode 100644 index 90c0c953..00000000 --- a/Deployment/devstack-scripts/pre-unstack.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -if [[ -z "$1" ]] ; then - SCRIPTS_DIR=$( cd $( dirname "$0" ) && pwd ) - source $SCRIPTS_DIR/localrc -fi - diff --git a/Deployment/devstack-scripts/ss1285.interfaces.example b/Deployment/devstack-scripts/ss1285.interfaces.example deleted file mode 100644 index df25828d..00000000 --- a/Deployment/devstack-scripts/ss1285.interfaces.example +++ /dev/null @@ -1,53 +0,0 @@ -# This file describes the network interfaces available on your system -# and how to activate them. For more information, see interfaces(5). - -# The loopback network interface -auto lo -iface lo inet loopback - -# The primary network interface -auto eth0 -iface eth0 inet static - address 67.207.197.34 - netmask 255.255.255.240 - gateway 67.207.197.33 - # dns-* options are implemented by the resolvconf package, if installed - dns-nameservers 208.166.50.13 67.207.201.6 - dns-search svwh.net - - -auto eth0.260 -iface eth0.260 inet manual - vlan-raw-device eth0 - post-up ifconfig $IFACE 172.18.124.102/29 -# post-up route add -net 172.18.0.0/16 gw 172.18.124.97 -# pre-down route del -net 172.18.0.0/16 gw 172.18.124.97 - post-up ip route add default via 172.18.124.97 dev $IFACE table 260 - post-up ip rule add from 172.18.124.96/29 to 172.18.0.0/16 table 260 - pre-down ip rule del from 172.18.124.96/29 to 172.18.0.0/16 - pre-down ip route del table 260 - pre-down ifconfig $IFACE 0.0.0.0 - - -auto eth0.261 -iface eth0.261 inet manual - vlan-raw-device eth0 - post-up ifconfig $IFACE 172.18.124.202/26 - post-up route add -net 172.18.0.0/16 gw 172.18.124.193 dev $IFACE - pre-down route del -net 172.18.0.0/16 gw 172.18.124.193 dev $IFACE - pre-down ifconfig $IFACE 0.0.0.0 - - -auto eth1 -iface eth1 inet manual - up ifconfig $IFACE up - down ifconfig $IFACE down -# up ifconfig $IFACE 0.0.0.0 - - -#auto eth1.221 -#iface eth1.221 inet manual -# vlan-raw-device eth1 -# pre-up ifconfig $IFACE up -# post-down ifconfig $IFACE down -# up ifconfig $IFACE 0.0.0.0 diff --git a/Deployment/devstack-scripts/ss1383.interfaces.example b/Deployment/devstack-scripts/ss1383.interfaces.example deleted file mode 100644 index ae7e24e2..00000000 --- a/Deployment/devstack-scripts/ss1383.interfaces.example +++ /dev/null @@ -1,54 +0,0 @@ -# This file describes the network interfaces available on your system -# and how to activate them. For more information, see interfaces(5). - -# The loopback network interface -auto lo -iface lo inet loopback - -# The primary network interface -auto eth0 -iface eth0 inet static - address 67.207.197.36 - netmask 255.255.255.240 - network 67.207.197.32 - broadcast 67.207.197.47 - gateway 67.207.197.33 - # dns-* options are implemented by the resolvconf package, if installed - dns-nameservers 208.166.50.13 67.207.206.1 - dns-search svwh.net - - -auto eth0.260 -iface eth0.260 inet manual - vlan-raw-device eth0 - post-up ifconfig $IFACE 172.18.124.100/29 - post-up ip route add default via 172.18.124.97 dev $IFACE table 260 - post-up ip rule add from 172.18.124.96/29 to 172.18.0.0/16 table 260 - pre-down ip rule del from 172.18.124.96/29 to 172.18.0.0/16 table 260 - pre-down ip route del table 260 - pre-down ifconfig $IFACE 0.0.0.0 -# post-up route add -net 172.18.0.0/16 gw 172.18.124.97 -# post-down route del -net 172.18.0.0/16 gw 172.18.124.97 - - -auto eth1 -iface eth1 inet manual - up ifconfig $IFACE up - down ifconfig $IFACE down -# up ifconfig $IFACE 0.0.0.0 - - -auto eth0.261 -iface eth0.261 inet manual - vlan-raw-device eth0 - post-up ifconfig $IFACE 172.18.124.200/26 - post-up route add -net 172.18.0.0/16 gw 172.18.124.193 dev $IFACE - pre-down route del -net 172.18.0.0/16 gw 172.18.124.192 dev $IFACE - pre-down ifconfig $IFACE 0.0.0.0 - - -#auto eth1.221 -#iface eth1.221 inet manual -# vlan-raw-device eth1 -# pre-up ifconfig $IFACE up -# post-down ifcofnig $IFACE down diff --git a/Deployment/devstack-scripts/standalone/devstack.localrc b/Deployment/devstack-scripts/standalone/devstack.localrc deleted file mode 100644 index 441f9157..00000000 --- a/Deployment/devstack-scripts/standalone/devstack.localrc +++ /dev/null @@ -1,27 +0,0 @@ -# Devstack's config file for STANDALONE installation - -lab_id=101 -lab_password=swordfish - -HOST_IP=172.18.124.${lab_id} - -FIXED_RANGE=10.0.${lab_id}.0/24 - -FLAT_INTERFACE=eth1 - -ADMIN_PASSWORD=$lab_password -MYSQL_PASSWORD=$lab_password -RABBIT_PASSWORD=$lab_password -SERVICE_PASSWORD=$lab_password -SERVICE_TOKEN=tokentoken - -ENABLED_SERVICES+=,heat,h-api,h-api-cfn,h-api-cw,h-eng -ENABLED_SERVICES+=,conductor,portas - -SCREEN_LOGDIR=/opt/stack/log/ -LOGFILE=$SCREEN_LOGDIR/stack.sh.log - -API_RATE_LIMIT=False - -EXTRA_OPTS=(force_config_drive=true libvirt_images_type=qcow2 force_raw_images=false) - diff --git a/Deployment/devstack-scripts/start-devstack.sh b/Deployment/devstack-scripts/start-devstack.sh deleted file mode 100644 index 3797b833..00000000 --- a/Deployment/devstack-scripts/start-devstack.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/bash - -SCRIPTS_DIR=$( cd $( dirname "$0" ) && pwd ) - -source $SCRIPTS_DIR/localrc - -INSTALL_MODE="$1" - -validate_install_mode - - - -# Update devstack-scripts if multihost -#=============================================================================== -if [[ "$INSTALL_MODE" == 'multihost' ]] ; then - _echo "* Copying devstack-scripts to compute nodes ..." - for __compute_node in $COMPUTE_NODE_LIST ; do - _echo "** Removing devstack-scripts on '$__compute_node' ..." - ssh stack@$__compute_node rm -rf ~/devstack-scripts - _echo "** Copying devstack-scripts to '$__compute_node' ..." - scp -r $SCRIPTS_DIR stack@$__compute_node:~/ - done -fi -#=============================================================================== - - - -# Executing pre-stack actions -#=============================================================================== -_echo "* Executing pre-stack actions ..." -source $SCRIPTS_DIR/pre-stack.sh no-localrc -#=============================================================================== - - - -# Creating stack -#=============================================================================== -_echo "* Starting devstack ..." -$DEVSTACK_DIR/stack.sh -#=============================================================================== - - - -# Executing post-stack actions -#=============================================================================== -_echo "* Executing post-stack actions ..." -source $SCRIPTS_DIR/post-stack.sh no-localrc -#source $SCRIPTS_DIR/start-keero.sh no-localrc -#=============================================================================== - - - -# Start installation on compute nodes -#=============================================================================== -if [[ "$INSTALL_MODE" == 'multihost' ]] ; then - _echo "* Starting devstack on compute nodes ..." - for __compute_node in $COMPUTE_NODE_LIST ; do - _echo "** Starting devstack on '$__compute_node' ..." - ssh stack@$__compute_node $SCRIPTS_DIR/start-devstack.sh compute - done -fi -#=============================================================================== - diff --git a/Deployment/devstack-scripts/start-keero.sh b/Deployment/devstack-scripts/start-keero.sh deleted file mode 100644 index 82d45497..00000000 --- a/Deployment/devstack-scripts/start-keero.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -if [[ -z "$1" ]] ; then - SCRIPTS_DIR=$( cd $( dirname "$0" ) && pwd ) - source $SCRIPTS_DIR/localrc -fi - -die_if_not_set INSTALL_DIR - -# Starting Portas -#================ -if [[ ! -d "$INSTALL_DIR/portas" ]] ; then - mkdir -p "$INSTALL_DIR/portas" -fi - -cp "$INSTALL_DIR/keero/portas/etc" "$INSTALL_DIR/portas/etc" - -screen_it portas "cd $INSTALL_DIR/portas && portas-api --config-file=$INSTALL_DIR/portas/etc/portas-api.conf" -#================ - - - -# Starting Conductor -#=================== -screen_it conductor "cd $INSTALL_DIR/keero/conductor && bash ./tools/with_venv.sh ./bin/app.py" -#=================== diff --git a/Deployment/devstack-scripts/start-vm.sh b/Deployment/devstack-scripts/start-vm.sh deleted file mode 100644 index a71b63ec..00000000 --- a/Deployment/devstack-scripts/start-vm.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -image_file=$1 - -function die { - echo "$@" - exit 1 -} - -[ -z "$image_file" ] && die "VM name MUST be provided!" -[ -f "$image_file" ] || die "File '$image_file' not found." - -echo "Starting VM '$image_file' ..." - -kvm \ - -m 2048 \ - -drive file="$image_file",if=virtio \ - -redir tcp:3389::3389 -redir tcp:3390::3390 \ - -nographic \ - -usbdevice tablet \ - -vnc :20 - diff --git a/Deployment/devstack-scripts/stop-devstack.sh b/Deployment/devstack-scripts/stop-devstack.sh deleted file mode 100644 index a88c5baf..00000000 --- a/Deployment/devstack-scripts/stop-devstack.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - -SCRIPTS_DIR=$( cd $( dirname "$0" ) && pwd ) - -source $SCRIPTS_DIR/localrc - -INSTALL_MODE="$1" - -validate_install_mode - - -# Executing pre-unstack actions -#=============================================================================== -_echo "* Executing pre-unstack actions ..." -source $SCRIPTS_DIR/pre-unstack.sh no-localrc -#=============================================================================== - - -# Executing unstack.sh -#=============================================================================== -_echo "* Executing stop devstack ..." -$DEVSTACK_DIR/unstack.sh -#=============================================================================== - - -# Executing post-unstack actions -#=============================================================================== -_echo "* Executing post-unstack actions ..." -source $SCRIPTS_DIR/post-unstack.sh no-localrc -#source $SCRIPTS_DIR/stop-keero.sh no-localrc -#=============================================================================== - - - -# Stop installation on compute nodes -#=============================================================================== -if [[ "$INSTALL_MODE" == 'multihost' ]] ; then - _echo "* Stopping devstack on compute nodes ..." - for $__compute_node in $COMPUTE_NODE_LIST ; do - _echo "** Stopping devstack on '$__compute_node' ..." - ssh stack@$__compute_node $SCRIPTS_DIR/stop-devstack.sh - done -fi -#=============================================================================== - diff --git a/Deployment/devstack-scripts/stop-keero.sh b/Deployment/devstack-scripts/stop-keero.sh deleted file mode 100644 index bf9ff5b9..00000000 --- a/Deployment/devstack-scripts/stop-keero.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -if [[ -z "$1" ]] ; then - SCRIPTS_DIR=$( cd $( dirname "$0" ) && pwd ) - source $SCRIPTS_DIR/localrc -fi - -# Stopping Keero components -#========================== -for serv in conductor portas ; do - screen -S $SCREEN_NAME -p $serv -X kill -done -#========================== diff --git a/WindowsAgent/ExecutionPlanGenerator/App.config b/ExecutionPlanGenerator/App.config similarity index 100% rename from WindowsAgent/ExecutionPlanGenerator/App.config rename to ExecutionPlanGenerator/App.config diff --git a/WindowsAgent/ExecutionPlanGenerator/ExecutionPlanGenerator.csproj b/ExecutionPlanGenerator/ExecutionPlanGenerator.csproj similarity index 100% rename from WindowsAgent/ExecutionPlanGenerator/ExecutionPlanGenerator.csproj rename to ExecutionPlanGenerator/ExecutionPlanGenerator.csproj diff --git a/WindowsAgent/ExecutionPlanGenerator/Program.cs b/ExecutionPlanGenerator/Program.cs similarity index 100% rename from WindowsAgent/ExecutionPlanGenerator/Program.cs rename to ExecutionPlanGenerator/Program.cs diff --git a/WindowsAgent/ExecutionPlanGenerator/Properties/AssemblyInfo.cs b/ExecutionPlanGenerator/Properties/AssemblyInfo.cs similarity index 100% rename from WindowsAgent/ExecutionPlanGenerator/Properties/AssemblyInfo.cs rename to ExecutionPlanGenerator/Properties/AssemblyInfo.cs diff --git a/WindowsAgent/ExecutionPlanGenerator/packages.config b/ExecutionPlanGenerator/packages.config similarity index 100% rename from WindowsAgent/ExecutionPlanGenerator/packages.config rename to ExecutionPlanGenerator/packages.config diff --git a/WindowsAgent/Tools/NuGet.exe b/Tools/NuGet.exe similarity index 100% rename from WindowsAgent/Tools/NuGet.exe rename to Tools/NuGet.exe diff --git a/WindowsAgent/WindowsAgent.sln b/WindowsAgent.sln similarity index 100% rename from WindowsAgent/WindowsAgent.sln rename to WindowsAgent.sln diff --git a/WindowsAgent/WindowsAgent/App.config b/WindowsAgent/App.config similarity index 100% rename from WindowsAgent/WindowsAgent/App.config rename to WindowsAgent/App.config diff --git a/WindowsAgent/WindowsAgent/ExecutionPlan.cs b/WindowsAgent/ExecutionPlan.cs similarity index 100% rename from WindowsAgent/WindowsAgent/ExecutionPlan.cs rename to WindowsAgent/ExecutionPlan.cs diff --git a/WindowsAgent/WindowsAgent/MqMessage.cs b/WindowsAgent/MqMessage.cs similarity index 100% rename from WindowsAgent/WindowsAgent/MqMessage.cs rename to WindowsAgent/MqMessage.cs diff --git a/WindowsAgent/WindowsAgent/PlanExecutor.cs b/WindowsAgent/PlanExecutor.cs similarity index 100% rename from WindowsAgent/WindowsAgent/PlanExecutor.cs rename to WindowsAgent/PlanExecutor.cs diff --git a/WindowsAgent/WindowsAgent/Program.cs b/WindowsAgent/Program.cs similarity index 100% rename from WindowsAgent/WindowsAgent/Program.cs rename to WindowsAgent/Program.cs diff --git a/WindowsAgent/WindowsAgent/Properties/AssemblyInfo.cs b/WindowsAgent/Properties/AssemblyInfo.cs similarity index 100% rename from WindowsAgent/WindowsAgent/Properties/AssemblyInfo.cs rename to WindowsAgent/Properties/AssemblyInfo.cs diff --git a/WindowsAgent/WindowsAgent/RabbitMqClient.cs b/WindowsAgent/RabbitMqClient.cs similarity index 100% rename from WindowsAgent/WindowsAgent/RabbitMqClient.cs rename to WindowsAgent/RabbitMqClient.cs diff --git a/WindowsAgent/WindowsAgent/SampleExecutionPlan.json b/WindowsAgent/SampleExecutionPlan.json similarity index 100% rename from WindowsAgent/WindowsAgent/SampleExecutionPlan.json rename to WindowsAgent/SampleExecutionPlan.json diff --git a/WindowsAgent/WindowsAgent/ServiceManager.cs b/WindowsAgent/ServiceManager.cs similarity index 100% rename from WindowsAgent/WindowsAgent/ServiceManager.cs rename to WindowsAgent/ServiceManager.cs diff --git a/WindowsAgent/WindowsAgent/WindowsAgent.csproj b/WindowsAgent/WindowsAgent.csproj similarity index 100% rename from WindowsAgent/WindowsAgent/WindowsAgent.csproj rename to WindowsAgent/WindowsAgent.csproj diff --git a/WindowsAgent/WindowsAgent/WindowsService.cs b/WindowsAgent/WindowsService.cs similarity index 100% rename from WindowsAgent/WindowsAgent/WindowsService.cs rename to WindowsAgent/WindowsService.cs diff --git a/WindowsAgent/WindowsAgent/WindowsServiceInstaller.cs b/WindowsAgent/WindowsServiceInstaller.cs similarity index 100% rename from WindowsAgent/WindowsAgent/WindowsServiceInstaller.cs rename to WindowsAgent/WindowsServiceInstaller.cs diff --git a/WindowsAgent/WindowsAgent/packages.config b/WindowsAgent/packages.config similarity index 100% rename from WindowsAgent/WindowsAgent/packages.config rename to WindowsAgent/packages.config diff --git a/api/.gitignore b/api/.gitignore deleted file mode 100644 index f5f39680..00000000 --- a/api/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -#IntelJ Idea -.idea/ - -#virtualenv -.venv/ - -#Build results -build/ -dist/ -*.egg-info/ - -#Python -*.pyc - -#Translation build -*.mo -*.pot - -#SQLite Database files -*.sqlite - -#Autogenerated Documentation -doc/source/api \ No newline at end of file diff --git a/api/README.rst b/api/README.rst deleted file mode 100644 index 02ee2a7c..00000000 --- a/api/README.rst +++ /dev/null @@ -1,7 +0,0 @@ -Glazier API README -===================== -Glazier API is a project that provides access to engine via API. - -SEE ALSO --------- -* `Glazier <http://glazier.mirantis.com>`__ diff --git a/api/babel.cfg b/api/babel.cfg deleted file mode 100644 index efceab81..00000000 --- a/api/babel.cfg +++ /dev/null @@ -1 +0,0 @@ -[python: **.py] diff --git a/api/bin/glazier-api b/api/bin/glazier-api deleted file mode 100755 index 24962190..00000000 --- a/api/bin/glazier-api +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License.from oslo.config import cfg - -import gettext -import os -import sys - -# If ../glazierapi/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -from glazierapi.common.service import TaskResultHandlerService - -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'portas', '__init__.py')): - sys.path.insert(0, possible_topdir) - -from glazierapi.common import config -from glazierapi.openstack.common import log -from glazierapi.openstack.common import wsgi -from glazierapi.openstack.common import service - -gettext.install('glazierapi', './glazierapi/locale', unicode=1) - -if __name__ == '__main__': - try: - config.parse_args() - log.setup('glazierapi') - - launcher = service.ServiceLauncher() - - api_service = wsgi.Service(config.load_paste_app(), - port=config.CONF.bind_port, - host=config.CONF.bind_host) - - launcher.launch_service(api_service) - launcher.launch_service(TaskResultHandlerService()) - launcher.wait() - except RuntimeError, e: - sys.stderr.write("ERROR: %s\n" % e) - sys.exit(1) diff --git a/api/doc/source/_static/.placeholder b/api/doc/source/_static/.placeholder deleted file mode 100755 index e69de29b..00000000 diff --git a/api/doc/source/_templates/.placeholder b/api/doc/source/_templates/.placeholder deleted file mode 100755 index e69de29b..00000000 diff --git a/api/doc/source/_theme/theme.conf b/api/doc/source/_theme/theme.conf deleted file mode 100755 index e8748699..00000000 --- a/api/doc/source/_theme/theme.conf +++ /dev/null @@ -1,2 +0,0 @@ -[theme] -inherit = default diff --git a/api/doc/source/conf.py b/api/doc/source/conf.py deleted file mode 100644 index 28c8b685..00000000 --- a/api/doc/source/conf.py +++ /dev/null @@ -1,241 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2010 OpenStack Foundation. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# -# Portas documentation build configuration file, created by -# sphinx-quickstart on Tue February 28 13:50:15 2013. -# -# This file is execfile()'d with the current directory set to its containing -# dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import os -import sys - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path = [os.path.abspath('../../glazierapi'), - os.path.abspath('../..'), - os.path.abspath('../../bin')] + sys.path - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', - 'sphinx.ext.intersphinx', - 'sphinx.ext.coverage', - 'sphinx.ext.pngmath', - 'sphinx.ext.ifconfig', - 'sphinx.ext.graphviz'] - -# Add any paths that contain templates here, relative to this directory. -templates_path = [] -if os.getenv('HUDSON_PUBLISH_DOCS'): - templates_path = ['_ga', '_templates'] -else: - templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'Glazier APIs' -copyright = u'2013, Mirantis, Inc' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -from glazierapi.version import version_info as portas_version -# The full version, including alpha/beta/rc tags. -release = portas_version.version_string_with_vcs() -# The short X.Y version. -version = portas_version.canonical_version_string() - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of documents that shouldn't be included in the build. -#unused_docs = [] - -# List of directories, relative to source directory, that shouldn't be searched -# for source files. -exclude_trees = ['api'] - -# The reST default role (for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -show_authors = True - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -modindex_common_prefix = ['glazierapi.'] - -# -- Options for man page output -------------------------------------------- - -# Grouping the document tree for man pages. -# List of tuples 'sourcefile', 'target', u'title', u'Authors name', 'manual' - -man_pages = [ - ('man/glazierapi', 'glazier-api', u'Glazier API Server', - [u'Mirantis, Inc'], 1) -] - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -html_theme_path = ["."] -html_theme = '_theme' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = ['_theme'] - -# The name for this set of Sphinx documents. If None, it defaults to -# "<project> v<release> documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' -git_cmd = "git log --pretty=format:'%ad, commit %h' --date=local -n1" -html_last_updated_fmt = os.popen(git_cmd).read() - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -html_use_modindex = False - -# If false, no index is generated. -html_use_index = False - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a <link> tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = '' - -# Output file base name for HTML help builder. -htmlhelp_basename = 'glazierapidoc' - - -# -- Options for LaTeX output ------------------------------------------------ - -# The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' - -# The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, -# documentclass [howto/manual]). -latex_documents = [ - ('index', 'Glazier.tex', u'Glazier Documentation', - u'Mirantis, Inc', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# Additional stuff for the LaTeX preamble. -#latex_preamble = '' - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_use_modindex = True - -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'python': ('http://docs.python.org/', None)} diff --git a/api/doc/source/index.rst b/api/doc/source/index.rst deleted file mode 100644 index 2073f005..00000000 --- a/api/doc/source/index.rst +++ /dev/null @@ -1,114 +0,0 @@ -.. - Copyright (c) 2013 Mirantis, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); you may - not use this file except in compliance with the License. You may obtain - a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - License for the specific language governing permissions and limitations - under the License. - -============================================== -Welcome to Glazier API Service! -============================================== - -Glazier API is a project that provides access to engine via API. - -This document describes Glazier API for contributors of the project, -and assumes that you are already familiar with Glazier API from an -`end-user perspective`_. - -.. _`end-user perspective`: http://glazier.mirantis.com/ - -This documentation is generated by the Sphinx toolkit and lives in the source -tree. - -Installation Guide -================== -Install -------- -1. Check out sources to some directory (<home>/glazier):: - - user@work:~/$ git clone ssh://<user>@gerrit.mirantis.com:29418/keero/keero.git - -2. Install Glazier API:: - - user@work:~/$ cd glazier/api && sudo python setup.py install - -Configure ---------- -1. Open first configuration file for editing:: - - user@work:~/$ cd glazier/api/etc && nano glazier-api.conf - -2. Configure according to you environment (please note rabbitmq section):: - - [DEFAULT] - # Show more verbose log output (sets INFO log level output) - verbose = True - # Show debugging output in logs (sets DEBUG log level output) - debug = True - # Address to bind the server to - bind_host = 0.0.0.0 - # Port the bind the server to - bind_port = 8082 - # Log to this file. Make sure the user running skeleton-api has - # permissions to write to this file! - log_file = /tmp/glazier-api.log - #A valid SQLAlchemy connection string for the metadata database - sql_connection = sqlite:///glazier.sqlite - - [reports] - results_exchange = task-results - results_queue = task-results - reports_exchange = task-reports - reports_queue = task-reports - - [rabbitmq] - host = localhost - port = 5672 - virtual_host = keero - login = keero - password = keero - -3. Open second configuration file for editing:: - - smelikyan@work:~/cd glazier/api/etc && nano glazier-api.conf - -4. Configure according to you environment (please note filter:authtoken section):: - - [pipeline:glazier-api] - pipeline = authtoken context apiv1app - [app:apiv1app] - paste.app_factory = glazierapi.api.v1.router:API.factory - [filter:context] - paste.filter_factory = glazierapi.api.middleware.context:ContextMiddleware.factory - - [filter:authtoken] - paste.filter_factory = keystoneclient.middleware.auth_token:filter_factory - auth_host = localhost - auth_port = 35357 - auth_protocol = http - admin_tenant_name = admin - admin_user = admin - admin_password = password - signing_dir = /tmp/keystone-signing-glazierapi - -Run ----- -Run Glazier API and supply valid configuration file:: - - user@work:~/$ glazier-api --config-file=./glazier/api/etc/glazier-api.conf - -Man Pages -========= - -.. toctree:: - :maxdepth: 1 - - man/glazierapi diff --git a/api/doc/source/man/glazierapi.rst b/api/doc/source/man/glazierapi.rst deleted file mode 100644 index a488935b..00000000 --- a/api/doc/source/man/glazierapi.rst +++ /dev/null @@ -1,69 +0,0 @@ -.. - Copyright (c) 2013 Mirantis, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); you may - not use this file except in compliance with the License. You may obtain - a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - License for the specific language governing permissions and limitations - under the License. - -========== -glazier-api -========== - ------------------------------ -Glazier API Server ------------------------------ - -:Author: smelikyan@mirantis.com -:Date: 2013-04-04 -:Copyright: Mirantis, Inc. -:Version: 2013.1-dev -:Manual section: 1 -:Manual group: cloud computing - - -SYNOPSIS -======== - - glazier-api [options] - -DESCRIPTION -=========== - -glazier-api is a server daemon that serves the Glazier API - -OPTIONS -======= - - **General options** - - **-v, --verbose** - Print more verbose output - - **--config-file** - Config file used for running service - - **--bind-host=HOST** - Address of host running ``glazier-api``. Defaults to `0.0.0.0`. - - **--bind-port=PORT** - Port that ``glazier-api`` listens on. Defaults to `8082`. - - -FILES -===== - -* /etc/glazier/glazier-api.conf -* /etc/glazier/glazier-api-paste.conf - -SEE ALSO -======== - -* `Glazier <http://glazier.mirantis.com>`__ diff --git a/api/etc/glazier-api-paste.ini b/api/etc/glazier-api-paste.ini deleted file mode 100644 index f02d0c14..00000000 --- a/api/etc/glazier-api-paste.ini +++ /dev/null @@ -1,18 +0,0 @@ -[pipeline:glazier-api] -pipeline = authtoken context apiv1app - -[app:apiv1app] -paste.app_factory = glazierapi.api.v1.router:API.factory - -[filter:context] -paste.filter_factory = glazierapi.api.middleware.context:ContextMiddleware.factory - -[filter:authtoken] -paste.filter_factory = keystoneclient.middleware.auth_token:filter_factory -auth_host = localhost -auth_port = 35357 -auth_protocol = http -admin_tenant_name = admin -admin_user = admin -admin_password = password -signing_dir = /tmp/keystone-signing-portas diff --git a/api/etc/glazier-api.conf b/api/etc/glazier-api.conf deleted file mode 100644 index 5cf698e8..00000000 --- a/api/etc/glazier-api.conf +++ /dev/null @@ -1,32 +0,0 @@ -[DEFAULT] -# Show more verbose log output (sets INFO log level output) -verbose = True - -# Show debugging output in logs (sets DEBUG log level output) -debug = True - -# Address to bind the server to -bind_host = 0.0.0.0 - -# Port the bind the server to -bind_port = 8082 - -# Log to this file. Make sure the user running skeleton-api has -# permissions to write to this file! -log_file = /tmp/portas-api.log - -#A valid SQLAlchemy connection string for the metadata database -sql_connection = sqlite:///glazier.sqlite - -[reports] -results_exchange = task-results -results_queue = task-results -reports_exchange = task-reports -reports_queue = task-reports - -[rabbitmq] -host = localhost -port = 5672 -virtual_host = keero -login = keero -password = keero diff --git a/api/glazierapi/__init__.py b/api/glazierapi/__init__.py deleted file mode 100644 index 207fa154..00000000 --- a/api/glazierapi/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. \ No newline at end of file diff --git a/api/glazierapi/api/__init__.py b/api/glazierapi/api/__init__.py deleted file mode 100644 index fc46f490..00000000 --- a/api/glazierapi/api/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License.from oslo.config import cfg - diff --git a/api/glazierapi/api/middleware/__init__.py b/api/glazierapi/api/middleware/__init__.py deleted file mode 100644 index fc46f490..00000000 --- a/api/glazierapi/api/middleware/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License.from oslo.config import cfg - diff --git a/api/glazierapi/api/middleware/context.py b/api/glazierapi/api/middleware/context.py deleted file mode 100644 index 6d82abde..00000000 --- a/api/glazierapi/api/middleware/context.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License.from oslo.config import cfg - - -import json -from oslo.config import cfg - -import webob.exc - -from glazierapi.openstack.common import wsgi -import glazierapi.context -import glazierapi.openstack.common.log as logging - -CONF = cfg.CONF -LOG = logging.getLogger(__name__) - - -class BaseContextMiddleware(wsgi.Middleware): - def process_response(self, resp): - try: - request_id = resp.request.context.request_id - except AttributeError: - LOG.warn(_('Unable to retrieve request id from context')) - else: - resp.headers['x-openstack-request-id'] = 'req-%s' % request_id - return resp - - -class ContextMiddleware(BaseContextMiddleware): - def process_request(self, req): - """Convert authentication information into a request context - - Generate a glazierapi.context.RequestContext object from the available - authentication headers and store on the 'context' attribute - of the req object. - - :param req: wsgi request object that will be given the context object - :raises webob.exc.HTTPUnauthorized: when value of the X-Identity-Status - header is not 'Confirmed' and - anonymous access is disallowed - """ - if req.headers.get('X-Identity-Status') == 'Confirmed': - roles_header = req.headers.get('X-Roles', '') - roles = [r.strip().lower() for r in roles_header.split(',')] - - #NOTE(bcwaldon): This header is deprecated in favor of X-Auth-Token - deprecated_token = req.headers.get('X-Storage-Token') - - service_catalog = None - if req.headers.get('X-Service-Catalog') is not None: - try: - catalog_header = req.headers.get('X-Service-Catalog') - service_catalog = json.loads(catalog_header) - except ValueError: - raise webob.exc.HTTPInternalServerError( - _('Invalid service catalog json.')) - - kwargs = { - 'user': req.headers.get('X-User-Id'), - 'tenant': req.headers.get('X-Tenant-Id'), - 'roles': roles, - 'auth_token': req.headers.get('X-Auth-Token', - deprecated_token), - 'service_catalog': service_catalog, - 'session': req.headers.get('X-Configuration-Session') - } - req.context = glazierapi.context.RequestContext(**kwargs) - else: - raise webob.exc.HTTPUnauthorized() - - @classmethod - def factory(cls, global_conf, **local_conf): - def filter(app): - return cls(app) - return filter diff --git a/api/glazierapi/api/v1/__init__.py b/api/glazierapi/api/v1/__init__.py deleted file mode 100644 index 7a46398e..00000000 --- a/api/glazierapi/api/v1/__init__.py +++ /dev/null @@ -1,110 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License.from oslo.config import cfg - -from glazierapi.db.models import Session, Environment, Status -from glazierapi.db.session import get_session - - -def get_draft(environment_id=None, session_id=None): - unit = get_session() - #TODO: When session is deployed should be returned env.description - if session_id: - session = unit.query(Session).get(session_id) - return session.description - else: - environment = unit.query(Environment).get(environment_id) - return environment.description - - -def save_draft(session_id, draft): - unit = get_session() - session = unit.query(Session).get(session_id) - - session.description = draft - session.save(unit) - - -def get_env_status(environment_id, session_id): - status = 'draft' - - unit = get_session() - - if not session_id: - variants = ['open', 'deploying'] - session = unit.query(Session).filter( - Session.environment_id == environment_id and - Session.state.in_(variants) - ).first() - if session: - session_id = session.id - else: - return status - - session_state = unit.query(Session).get(session_id).state - reports_count = unit.query(Status).filter_by(environment_id=environment_id, - session_id=session_id).count() - - if session_state == 'deployed': - status = 'finished' - - if session_state == 'deploying' and reports_count > 1: - status = 'pending' - - draft = get_draft(environment_id, session_id) - - if not 'services' in draft: - return 'pending' - - def get_statuses(type): - if type in draft['services']: - services = draft['services'][type] - return [get_service_status(environment_id, - session_id, - service) for service in services] - else: - return [] - - is_inprogress = filter(lambda item: item == 'inprogress', - get_statuses('activeDirectories') + - get_statuses('webServers')) - - if session_state == 'deploying' and is_inprogress > 1: - status = 'inprogress' - - return status - - -def get_service_status(environment_id, session_id, service): - status = 'draft' - - unit = get_session() - session_state = unit.query(Session).get(session_id).state - - entities = [u['id'] for u in service['units']] - reports_count = unit.query(Status).filter( - Status.environment_id == environment_id - and Status.session_id == session_id - and Status.entity_id.in_(entities) - ).count() - - if session_state == 'deployed': - status = 'finished' - - if session_state == 'deploying' and reports_count == 0: - status = 'pending' - - if session_state == 'deploying' and reports_count > 0: - status = 'inprogress' - - return status diff --git a/api/glazierapi/api/v1/active_directories.py b/api/glazierapi/api/v1/active_directories.py deleted file mode 100644 index 12416b1c..00000000 --- a/api/glazierapi/api/v1/active_directories.py +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License.from oslo.config import cfg - -from glazierapi import utils -from glazierapi.api.v1 import save_draft, get_draft, get_service_status -from glazierapi.common import uuidutils -from glazierapi.openstack.common import wsgi, timeutils -from glazierapi.openstack.common import log as logging - -log = logging.getLogger(__name__) - - -class Controller(object): - def index(self, request, environment_id): - log.debug(_('ActiveDirectory:Index <EnvId: {0}>'. - format(environment_id))) - - draft = prepare_draft(get_draft(environment_id, - request.context.session)) - - for dc in draft['services']['activeDirectories']: - dc['status'] = get_service_status(environment_id, - request.context.session, - dc) - - return {'activeDirectories': draft['services']['activeDirectories']} - - @utils.verify_session - def create(self, request, environment_id, body): - log.debug(_('ActiveDirectory:Create <EnvId: {0}, Body: {1}>'. - format(environment_id, body))) - - draft = get_draft(session_id=request.context.session) - - active_directory = body.copy() - active_directory['id'] = uuidutils.generate_uuid() - active_directory['created'] = str(timeutils.utcnow()) - active_directory['updated'] = str(timeutils.utcnow()) - - unit_count = 0 - for unit in active_directory['units']: - unit_count += 1 - unit['id'] = uuidutils.generate_uuid() - unit['name'] = 'dc{0}'.format(unit_count) - - draft = prepare_draft(draft) - draft['services']['activeDirectories'].append(active_directory) - save_draft(request.context.session, draft) - - return active_directory - - def delete(self, request, environment_id, active_directory_id): - log.debug(_('ActiveDirectory:Delete <EnvId: {0}, Id: {1}>'. - format(environment_id, active_directory_id))) - - draft = get_draft(request.context.session) - items = [service for service in draft['services']['activeDirectories'] - if service['id'] != active_directory_id] - draft['services']['activeDirectories'] = items - save_draft(request.context.session, draft) - - -def prepare_draft(draft): - if not 'services' in draft: - draft['services'] = {} - - if not 'activeDirectories' in draft['services']: - draft['services']['activeDirectories'] = [] - - return draft - - -def create_resource(): - return wsgi.Resource(Controller()) diff --git a/api/glazierapi/api/v1/environments.py b/api/glazierapi/api/v1/environments.py deleted file mode 100644 index 5bb67022..00000000 --- a/api/glazierapi/api/v1/environments.py +++ /dev/null @@ -1,132 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License.from oslo.config import cfg - -from amqplib.client_0_8 import Message -import anyjson -import eventlet -from webob import exc -from glazierapi.common import config -from glazierapi.api.v1 import get_env_status -from glazierapi.db.session import get_session -from glazierapi.db.models import Environment -from glazierapi.openstack.common import wsgi -from glazierapi.openstack.common import log as logging - -amqp = eventlet.patcher.import_patched('amqplib.client_0_8') -rabbitmq = config.CONF.rabbitmq - -log = logging.getLogger(__name__) - - -class Controller(object): - def index(self, request): - log.debug(_('Environments:List')) - - #Only environments from same tenant as users should be shown - filters = {'tenant_id': request.context.tenant} - - session = get_session() - environments = session.query(Environment).filter_by(**filters) - environments = [env.to_dict() for env in environments] - - for env in environments: - env['status'] = get_env_status(env['id'], request.context.session) - - return {"environments": environments} - - def create(self, request, body): - log.debug(_('Environments:Create <Body {0}>'.format(body))) - - #tagging environment by tenant_id for later checks - params = body.copy() - params['tenant_id'] = request.context.tenant - - environment = Environment() - environment.update(params) - - session = get_session() - with session.begin(): - session.add(environment) - - #saving environment as Json to itself - environment.update({"description": environment.to_dict()}) - environment.save(session) - - return environment.to_dict() - - def show(self, request, environment_id): - log.debug(_('Environments:Show <Id: {0}>'.format(environment_id))) - - session = get_session() - environment = session.query(Environment).get(environment_id) - - if environment.tenant_id != request.context.tenant: - log.info('User is not authorized to access this tenant resources.') - raise exc.HTTPUnauthorized - - env = environment.to_dict() - env['status'] = get_env_status(environment_id, request.context.session) - - return env - - def update(self, request, environment_id, body): - log.debug(_('Environments:Update <Id: {0}, Body: {1}>'. - format(environment_id, body))) - - session = get_session() - environment = session.query(Environment).get(environment_id) - - if environment.tenant_id != request.context.tenant: - log.info('User is not authorized to access this tenant resources.') - raise exc.HTTPUnauthorized - - environment.update(body) - environment.save(session) - - return environment.to_dict() - - def delete(self, request, environment_id): - log.debug(_('Environments:Delete <Id: {0}>'.format(environment_id))) - - session = get_session() - environment = session.query(Environment).get(environment_id) - - with session.begin(): - session.delete(environment) - - #preparing data for removal from conductor - env = environment.description - env['services'] = [] - env['deleted'] = True - #Set X-Auth-Token for conductor - env['token'] = request.context.auth_token - - connection = amqp.Connection('{0}:{1}'. - format(rabbitmq.host, rabbitmq.port), - virtual_host=rabbitmq.virtual_host, - userid=rabbitmq.login, - password=rabbitmq.password, - ssl=rabbitmq.use_ssl, insist=True) - channel = connection.channel() - channel.exchange_declare('tasks', 'direct', durable=True, - auto_delete=False) - - channel.basic_publish(Message(body=anyjson.serialize(env)), 'tasks', - 'tasks') - - return None - - -def create_resource(): - return wsgi.Resource(Controller()) diff --git a/api/glazierapi/api/v1/router.py b/api/glazierapi/api/v1/router.py deleted file mode 100644 index 998ee316..00000000 --- a/api/glazierapi/api/v1/router.py +++ /dev/null @@ -1,106 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License.from oslo.config import cfg - -import routes -from glazierapi.openstack.common import wsgi -from glazierapi.api.v1 import (environments, sessions, - active_directories, webservers) - - -class API(wsgi.Router): - @classmethod - def factory(cls, global_conf, **local_conf): - return cls(routes.Mapper()) - - def __init__(self, mapper): - environments_resource = environments.create_resource() - mapper.connect('/environments', - controller=environments_resource, - action='index', - conditions={'method': ['GET']}) - mapper.connect('/environments', - controller=environments_resource, - action='create', - conditions={'method': ['POST']}) - mapper.connect('/environments/{environment_id}', - controller=environments_resource, - action='update', - conditions={'method': ['PUT']}) - mapper.connect('/environments/{environment_id}', - controller=environments_resource, - action='show', - conditions={'method': ['GET']}) - mapper.connect('/environments/{environment_id}', - controller=environments_resource, - action='delete', - conditions={'method': ['DELETE']}) - - sessions_resource = sessions.create_resource() - mapper.connect('/environments/{environment_id}/sessions', - controller=sessions_resource, - action='index', - conditions={'method': ['GET']}) - mapper.connect('/environments/{environment_id}/configure', - controller=sessions_resource, - action='configure', - conditions={'method': ['POST']}) - mapper.connect('/environments/{environment_id}/sessions/{session_id}', - controller=sessions_resource, - action='show', - conditions={'method': ['GET']}) - mapper.connect('/environments/{environment_id}/sessions/{session_id}', - controller=sessions_resource, - action='delete', - conditions={'method': ['DELETE']}) - mapper.connect('/environments/{environment_id}/sessions/' - '{session_id}/reports', - controller=sessions_resource, - action='reports', - conditions={'method': ['GET']}) - mapper.connect('/environments/{environment_id}/sessions/' - '{session_id}/deploy', - controller=sessions_resource, - action='deploy', - conditions={'method': ['POST']}) - - activeDirectories_resource = active_directories.create_resource() - mapper.connect('/environments/{environment_id}/activeDirectories', - controller=activeDirectories_resource, - action='index', - conditions={'method': ['GET']}) - mapper.connect('/environments/{environment_id}/activeDirectories', - controller=activeDirectories_resource, - action='create', - conditions={'method': ['POST']}) - mapper.connect('/environments/{environment_id}/activeDirectories/' - '{active_directory_id}', - controller=activeDirectories_resource, - action='delete', - conditions={'method': ['DELETE']}) - - webServers_resource = webservers.create_resource() - mapper.connect('/environments/{environment_id}/webServers', - controller=webServers_resource, - action='index', - conditions={'method': ['GET']}) - mapper.connect('/environments/{environment_id}/webServers', - controller=webServers_resource, - action='create', - conditions={'method': ['POST']}) - mapper.connect('/environments/{environment_id}/webServers/' - '{web_server_id}', - controller=webServers_resource, - action='delete', - conditions={'method': ['DELETE']}) - super(API, self).__init__(mapper) diff --git a/api/glazierapi/api/v1/sessions.py b/api/glazierapi/api/v1/sessions.py deleted file mode 100644 index 15654461..00000000 --- a/api/glazierapi/api/v1/sessions.py +++ /dev/null @@ -1,168 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License.from oslo.config import cfg - -from amqplib.client_0_8 import Message -import anyjson -import eventlet -from webob import exc -from glazierapi.common import config -from glazierapi.db.models import Session, Status, Environment -from glazierapi.db.session import get_session -from glazierapi.openstack.common import wsgi -from glazierapi.openstack.common import log as logging - -amqp = eventlet.patcher.import_patched('amqplib.client_0_8') -rabbitmq = config.CONF.rabbitmq -log = logging.getLogger(__name__) - - -class Controller(object): - def index(self, request, environment_id): - log.debug(_('Session:List <EnvId: {0}>'.format(environment_id))) - - filters = {'environment_id': environment_id, - 'user_id': request.context.user} - - unit = get_session() - configuration_sessions = unit.query(Session).filter_by(**filters) - - sessions = [session.to_dict() for session in configuration_sessions if - session.environment.tenant_id == request.context.tenant] - return {"sessions": sessions} - - def configure(self, request, environment_id): - log.debug(_('Session:Configure <EnvId: {0}>'.format(environment_id))) - - params = {'environment_id': environment_id, - 'user_id': request.context.user, 'state': 'open'} - - session = Session() - session.update(params) - - unit = get_session() - if unit.query(Session).filter( - Session.environment_id == environment_id and - Session.state.in_(['open', 'deploying']) - ).first(): - log.info('There is already open session for this environment') - raise exc.HTTPConflict - - #create draft for apply later changes - environment = unit.query(Environment).get(environment_id) - session.description = environment.description - - with unit.begin(): - unit.add(session) - - return session.to_dict() - - def show(self, request, environment_id, session_id): - log.debug(_('Session:Show <EnvId: {0}, ' - 'SessionId: {1}>'.format(environment_id, session_id))) - - unit = get_session() - session = unit.query(Session).get(session_id) - - if session.environment.tenant_id != request.context.tenant: - log.info('User is not authorized to access this tenant resources.') - raise exc.HTTPUnauthorized - - return session.to_dict() - - def delete(self, request, environment_id, session_id): - log.debug(_('Session:Delete <EnvId: {0}, ' - 'SessionId: {1}>'.format(environment_id, session_id))) - - unit = get_session() - session = unit.query(Session).get(session_id) - - comment = 'Session object in \'deploying\' state could not be deleted' - if session.state == 'deploying': - log.info(comment) - raise exc.HTTPForbidden(comment=comment) - - with unit.begin(): - unit.delete(session) - - return None - - def reports(self, request, environment_id, session_id): - log.debug(_('Session:Reports <EnvId: {0}, ' - 'SessionId: {1}>'.format(environment_id, session_id))) - - unit = get_session() - statuses = unit.query(Status).filter_by(session_id=session_id).all() - result = statuses - - if 'service_id' in request.GET: - service_id = request.GET['service_id'] - - environment = unit.query(Session).get(session_id).description - services = [] - if 'services' in environment and 'activeDirectories' in\ - environment['services']: - services += environment['services']['activeDirectories'] - - if 'services' in environment and 'webServers' in\ - environment['services']: - services += environment['services']['webServers'] - - service = [service for service in services - if service['id'] == service_id][0] - - if service: - entities = [u['id'] for u in service['units']] - entities.append(service_id) - result = [] - for status in statuses: - if status.entity_id in entities: - result.append(status) - - return {'reports': [status.to_dict() for status in result]} - - def deploy(self, request, environment_id, session_id): - log.debug(_('Session:Deploy <EnvId: {0}, ' - 'SessionId: {1}>'.format(environment_id, session_id))) - - unit = get_session() - session = unit.query(Session).get(session_id) - - msg = _('Could not deploy session. Session is already ' - 'deployed or in deployment state') - if session.state != 'open': - log.warn(msg) - - session.state = 'deploying' - session.save(unit) - - #Set X-Auth-Token for conductor - env = session.description - env['token'] = request.context.auth_token - - connection = amqp.Connection('{0}:{1}'. - format(rabbitmq.host, rabbitmq.port), - virtual_host=rabbitmq.virtual_host, - userid=rabbitmq.login, - password=rabbitmq.password, - ssl=rabbitmq.use_ssl, insist=True) - channel = connection.channel() - channel.exchange_declare('tasks', 'direct', durable=True, - auto_delete=False) - - channel.basic_publish(Message(body=anyjson.serialize(env)), 'tasks', - 'tasks') - - -def create_resource(): - return wsgi.Resource(Controller()) diff --git a/api/glazierapi/api/v1/webservers.py b/api/glazierapi/api/v1/webservers.py deleted file mode 100644 index 876c9d2c..00000000 --- a/api/glazierapi/api/v1/webservers.py +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License.from oslo.config import cfg - -from glazierapi import utils -from glazierapi.api.v1 import save_draft, get_draft, get_service_status -from glazierapi.common import uuidutils -from glazierapi.openstack.common import wsgi, timeutils -from glazierapi.openstack.common import log as logging - -log = logging.getLogger(__name__) - - -class Controller(object): - def index(self, request, environment_id): - log.debug(_('WebServer:List <EnvId: {0}>'.format(environment_id))) - - draft = prepare_draft(get_draft(environment_id, - request.context.session)) - - for dc in draft['services']['webServers']: - dc['status'] = get_service_status(environment_id, - request.context.session, dc) - - return {'webServers': draft['services']['webServers']} - - @utils.verify_session - def create(self, request, environment_id, body): - log.debug(_('WebServer:Create <EnvId: {0}, Body: {1}>'. - format(environment_id, body))) - - draft = get_draft(session_id=request.context.session) - - webServer = body.copy() - webServer['id'] = uuidutils.generate_uuid() - webServer['created'] = str(timeutils.utcnow()) - webServer['updated'] = str(timeutils.utcnow()) - - unit_count = 0 - for unit in webServer['units']: - unit_count += 1 - unit['id'] = uuidutils.generate_uuid() - unit['name'] = webServer['name'] + '_instance_' + str(unit_count) - - draft = prepare_draft(draft) - draft['services']['webServers'].append(webServer) - save_draft(request.context.session, draft) - - return webServer - - @utils.verify_session - def delete(self, request, environment_id, web_server_id): - log.debug(_('WebServer:Delete <EnvId: {0}, Id: {1}>'. - format(environment_id, web_server_id))) - - draft = get_draft(session_id=request.context.session) - - elements = [service for service in draft['services']['webServers'] if - service['id'] != web_server_id] - draft['services']['webServers'] = elements - save_draft(request.context.session, draft) - - -def prepare_draft(draft): - if not 'services' in draft: - draft['services'] = {} - - if not 'webServers' in draft['services']: - draft['services']['webServers'] = [] - - return draft - - -def create_resource(): - return wsgi.Resource(Controller()) diff --git a/api/glazierapi/common/__init__.py b/api/glazierapi/common/__init__.py deleted file mode 100644 index fc46f490..00000000 --- a/api/glazierapi/common/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License.from oslo.config import cfg - diff --git a/api/glazierapi/common/config.py b/api/glazierapi/common/config.py deleted file mode 100644 index a5bfd854..00000000 --- a/api/glazierapi/common/config.py +++ /dev/null @@ -1,205 +0,0 @@ -#!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Routines for configuring Glance -""" - -import logging -import logging.config -import logging.handlers -import os -import sys - -from oslo.config import cfg -from paste import deploy - -from glazierapi.version import version_info as version - -paste_deploy_opts = [ - cfg.StrOpt('flavor'), - cfg.StrOpt('config_file'), -] - -bind_opts = [ - cfg.StrOpt('bind-host', default='0.0.0.0'), - cfg.IntOpt('bind-port', default='8082'), -] - -reports_opts = [ - cfg.StrOpt('results_exchange', default='task-results'), - cfg.StrOpt('results_queue', default='task-results'), - cfg.StrOpt('reports_exchange', default='task-reports'), - cfg.StrOpt('reports_queue', default='task-reports') -] - -rabbit_opts = [ - cfg.StrOpt('host', default='localhost'), - cfg.IntOpt('port', default=5672), - cfg.BoolOpt('use_ssl', default=False), - cfg.StrOpt('login', default='guest'), - cfg.StrOpt('password', default='guest'), - cfg.StrOpt('virtual_host', default='/'), -] - -CONF = cfg.CONF -CONF.register_opts(paste_deploy_opts, group='paste_deploy') -CONF.register_cli_opts(bind_opts) -# CONF.register_opts(bind_opts) -CONF.register_opts(reports_opts, group='reports') -CONF.register_opts(rabbit_opts, group='rabbitmq') - - -CONF.import_opt('verbose', 'glazierapi.openstack.common.log') -CONF.import_opt('debug', 'glazierapi.openstack.common.log') -CONF.import_opt('log_dir', 'glazierapi.openstack.common.log') -CONF.import_opt('log_file', 'glazierapi.openstack.common.log') -CONF.import_opt('log_config', 'glazierapi.openstack.common.log') -CONF.import_opt('log_format', 'glazierapi.openstack.common.log') -CONF.import_opt('log_date_format', 'glazierapi.openstack.common.log') -CONF.import_opt('use_syslog', 'glazierapi.openstack.common.log') -CONF.import_opt('syslog_log_facility', 'glazierapi.openstack.common.log') - - -def parse_args(args=None, usage=None, default_config_files=None): - CONF(args=args, - project='glazierapi', - version=version.cached_version_string(), - usage=usage, - default_config_files=default_config_files) - - -def setup_logging(): - """ - Sets up the logging options for a log with supplied name - """ - - if CONF.log_config: - # Use a logging configuration file for all settings... - if os.path.exists(CONF.log_config): - logging.config.fileConfig(CONF.log_config) - return - else: - raise RuntimeError("Unable to locate specified logging " - "config file: %s" % CONF.log_config) - - root_logger = logging.root - if CONF.debug: - root_logger.setLevel(logging.DEBUG) - elif CONF.verbose: - root_logger.setLevel(logging.INFO) - else: - root_logger.setLevel(logging.WARNING) - - formatter = logging.Formatter(CONF.log_format, CONF.log_date_format) - - if CONF.use_syslog: - try: - facility = getattr(logging.handlers.SysLogHandler, - CONF.syslog_log_facility) - except AttributeError: - raise ValueError(_("Invalid syslog facility")) - - handler = logging.handlers.SysLogHandler(address='/dev/log', - facility=facility) - elif CONF.log_file: - logfile = CONF.log_file - if CONF.log_dir: - logfile = os.path.join(CONF.log_dir, logfile) - handler = logging.handlers.WatchedFileHandler(logfile) - else: - handler = logging.StreamHandler(sys.stdout) - - handler.setFormatter(formatter) - root_logger.addHandler(handler) - - -def _get_deployment_flavor(): - """ - Retrieve the paste_deploy.flavor config item, formatted appropriately - for appending to the application name. - """ - flavor = CONF.paste_deploy.flavor - return '' if not flavor else ('-' + flavor) - - -def _get_paste_config_path(): - paste_suffix = '-paste.ini' - conf_suffix = '.conf' - if CONF.config_file: - # Assume paste config is in a paste.ini file corresponding - # to the last config file - path = CONF.config_file[-1].replace(conf_suffix, paste_suffix) - else: - path = CONF.prog + '-paste.ini' - return CONF.find_file(os.path.basename(path)) - - -def _get_deployment_config_file(): - """ - Retrieve the deployment_config_file config item, formatted as an - absolute pathname. - """ - path = CONF.paste_deploy.config_file - if not path: - path = _get_paste_config_path() - if not path: - msg = "Unable to locate paste config file for %s." % CONF.prog - raise RuntimeError(msg) - return os.path.abspath(path) - - -def load_paste_app(app_name=None): - """ - Builds and returns a WSGI app from a paste config file. - - We assume the last config file specified in the supplied ConfigOpts - object is the paste config file. - - :param app_name: name of the application to load - - :raises RuntimeError when config file cannot be located or application - cannot be loaded from config file - """ - if app_name is None: - app_name = CONF.prog - - # append the deployment flavor to the application name, - # in order to identify the appropriate paste pipeline - app_name += _get_deployment_flavor() - - conf_file = _get_deployment_config_file() - - try: - logger = logging.getLogger(__name__) - logger.debug(_("Loading %(app_name)s from %(conf_file)s"), - {'conf_file': conf_file, 'app_name': app_name}) - - app = deploy.loadapp("config:%s" % conf_file, name=app_name) - - # Log the options used when starting if we're in debug mode... - if CONF.debug: - CONF.log_opt_values(logger, logging.DEBUG) - - return app - except (LookupError, ImportError), e: - msg = _("Unable to load %(app_name)s from " - "configuration file %(conf_file)s." - "\nGot: %(e)r") % locals() - logger.error(msg) - raise RuntimeError(msg) diff --git a/api/glazierapi/common/service.py b/api/glazierapi/common/service.py deleted file mode 100644 index 8b2d7342..00000000 --- a/api/glazierapi/common/service.py +++ /dev/null @@ -1,116 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License.from oslo.config import cfg - -import anyjson -from eventlet import patcher -from glazierapi.db.models import Status, Session, Environment -from glazierapi.db.session import get_session - -amqp = patcher.import_patched('amqplib.client_0_8') - -from glazierapi.openstack.common import service -from glazierapi.openstack.common import log as logging -from glazierapi.common import config - -conf = config.CONF.reports -rabbitmq = config.CONF.rabbitmq -log = logging.getLogger(__name__) -channel = None - - -class TaskResultHandlerService(service.Service): - def __init__(self, threads=1000): - super(TaskResultHandlerService, self).__init__(threads) - - def start(self): - super(TaskResultHandlerService, self).start() - self.tg.add_thread(self._handle_results) - - def stop(self): - super(TaskResultHandlerService, self).stop() - - def _handle_results(self): - connection = amqp.Connection('{0}:{1}'. - format(rabbitmq.host, rabbitmq.port), - virtual_host=rabbitmq.virtual_host, - userid=rabbitmq.login, - password=rabbitmq.password, - ssl=rabbitmq.use_ssl, insist=True) - ch = connection.channel() - - def bind(exchange, queue): - if not exchange: - ch.exchange_declare(exchange, 'direct', durable=True, - auto_delete=False) - ch.queue_declare(queue, durable=True, auto_delete=False) - if not exchange: - ch.queue_bind(queue, exchange, queue) - - bind(conf.results_exchange, conf.results_queue) - bind(conf.reports_exchange, conf.reports_queue) - - ch.basic_consume(conf.results_exchange, callback=handle_result) - ch.basic_consume(conf.reports_exchange, callback=handle_report, - no_ack=True) - while ch.callbacks: - ch.wait() - - -def handle_report(msg): - log.debug(_('Got report message from orchestration engine:\n{0}'. - format(msg.body))) - - params = anyjson.deserialize(msg.body) - params['entity_id'] = params['id'] - del params['id'] - - status = Status() - status.update(params) - - session = get_session() - #connect with session - conf_session = session.query(Session).filter_by( - **{'environment_id': status.environment_id, - 'state': 'deploying'}).first() - status.session_id = conf_session.id - - with session.begin(): - session.add(status) - - -def handle_result(msg): - log.debug(_('Got result message from ' - 'orchestration engine:\n{0}'.format(msg.body))) - - environment_result = anyjson.deserialize(msg.body) - if 'deleted' in environment_result: - log.debug(_('Result for environment {0} is dropped. ' - 'Environment is deleted'.format(environment_result['id']))) - - msg.channel.basic_ack(msg.delivery_tag) - return - - session = get_session() - environment = session.query(Environment).get(environment_result['id']) - - environment.description = environment_result - environment.save(session) - - #close session - conf_session = session.query(Session).filter_by( - **{'environment_id': environment.id, 'state': 'deploying'}).first() - conf_session.state = 'deployed' - conf_session.save(session) - - msg.channel.basic_ack(msg.delivery_tag) diff --git a/api/glazierapi/common/uuidutils.py b/api/glazierapi/common/uuidutils.py deleted file mode 100644 index 86b85193..00000000 --- a/api/glazierapi/common/uuidutils.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License.from oslo.config import cfg - -import uuid - - -def generate_uuid(): - return str(uuid.uuid4()).replace('-', '') diff --git a/api/glazierapi/context.py b/api/glazierapi/context.py deleted file mode 100644 index 2bea96f5..00000000 --- a/api/glazierapi/context.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from glazierapi.openstack.common import uuidutils - - -class RequestContext(object): - """ - Stores information about the security context under which the user - accesses the system, as well as additional request information. - """ - - def __init__(self, auth_token=None, user=None, tenant=None, - roles=None, service_catalog=None, session=None): - - self.auth_token = auth_token - self.user = user - self.tenant = tenant - self.roles = roles or [] - self.request_id = uuidutils.generate_uuid() - self.service_catalog = service_catalog - self.session = session - - def to_dict(self): - # NOTE(ameade): These keys are named to correspond with the default - # format string for logging the context in openstack common - return { - 'request_id': self.request_id, - - #NOTE(bcwaldon): openstack-common logging expects 'user' - 'user': self.user, - 'user_id': self.user, - - #NOTE(bcwaldon): openstack-common logging expects 'tenant' - 'tenant': self.tenant, - 'tenant_id': self.tenant, - 'project_id': self.tenant, - - 'roles': self.roles, - 'auth_token': self.auth_token, - 'session': self.session - } - - @classmethod - def from_dict(cls, values): - return cls(**values) diff --git a/api/glazierapi/db/__init__.py b/api/glazierapi/db/__init__.py deleted file mode 100644 index 374c1328..00000000 --- a/api/glazierapi/db/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License.from oslo.config import cfg - -from oslo.config import cfg - -sql_connection_opt = cfg.StrOpt('sql_connection', - default='sqlite:///glazierapi.sqlite', - secret=True, - metavar='CONNECTION', - help='A valid SQLAlchemy connection ' - 'string for the metadata database. ' - 'Default: %(default)s') - -CONF = cfg.CONF -CONF.register_opt(sql_connection_opt) diff --git a/api/glazierapi/db/migrate_repo/README b/api/glazierapi/db/migrate_repo/README deleted file mode 100644 index 6218f8ca..00000000 --- a/api/glazierapi/db/migrate_repo/README +++ /dev/null @@ -1,4 +0,0 @@ -This is a database migration repository. - -More information at -http://code.google.com/p/sqlalchemy-migrate/ diff --git a/api/glazierapi/db/migrate_repo/__init__.py b/api/glazierapi/db/migrate_repo/__init__.py deleted file mode 100644 index 2f288d3c..00000000 --- a/api/glazierapi/db/migrate_repo/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# template repository default module diff --git a/api/glazierapi/db/migrate_repo/manage.py b/api/glazierapi/db/migrate_repo/manage.py deleted file mode 100644 index cc59d86b..00000000 --- a/api/glazierapi/db/migrate_repo/manage.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License.from oslo.config import cfg - - -from migrate.versioning.shell import main - -# This should probably be a console script entry point. -if __name__ == '__main__': - main(debug='False', repository='.') diff --git a/api/glazierapi/db/migrate_repo/migrate.cfg b/api/glazierapi/db/migrate_repo/migrate.cfg deleted file mode 100644 index 0f60e5a1..00000000 --- a/api/glazierapi/db/migrate_repo/migrate.cfg +++ /dev/null @@ -1,20 +0,0 @@ -[db_settings] -# Used to identify which repository this database is versioned under. -# You can use the name of your project. -repository_id=Glazier Migrations - -# The name of the database table used to track the schema version. -# This name shouldn't already be used by your project. -# If this is changed once a database is under version control, you'll need to -# change the table name in each database too. -version_table=migrate_version - -# When committing a change script, Migrate will attempt to generate the -# sql for all supported databases; normally, if one of them fails - probably -# because you don't have that database installed - it is ignored and the -# commit continues, perhaps ending successfully. -# Databases in this list MUST compile successfully during a commit, or the -# entire commit will fail. List the databases your application will actually -# be using to ensure your updates to that database work properly. -# This must be a list; example: ['glazier','sqlite'] -required_dbs=[] diff --git a/api/glazierapi/db/migrate_repo/versions/001_add_initial_tables.py b/api/glazierapi/db/migrate_repo/versions/001_add_initial_tables.py deleted file mode 100644 index 8f74d10c..00000000 --- a/api/glazierapi/db/migrate_repo/versions/001_add_initial_tables.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License.from oslo.config import cfg - -from sqlalchemy.schema import MetaData, Table, Column, ForeignKey -from sqlalchemy.types import String, Text, DateTime - - -meta = MetaData() - -Table('environment', meta, - Column('id', String(32), primary_key=True), - Column('name', String(255), nullable=False), - Column('created', DateTime(), nullable=False), - Column('updated', DateTime(), nullable=False), - Column('tenant_id', String(32), nullable=False), - Column('description', Text(), nullable=False), - ) - -Table('service', meta, - Column('id', String(32), primary_key=True), - Column('name', String(255), nullable=False), - Column('type', String(40), nullable=False), - Column('environment_id', String(32), ForeignKey('environment.id')), - Column('created', DateTime, nullable=False), - Column('updated', DateTime, nullable=False), - Column('description', Text(), nullable=False), - ) - - -def upgrade(migrate_engine): - meta.bind = migrate_engine - meta.create_all() - - -def downgrade(migrate_engine): - meta.bind = migrate_engine - meta.drop_all() diff --git a/api/glazierapi/db/migrate_repo/versions/002_add_session_table.py b/api/glazierapi/db/migrate_repo/versions/002_add_session_table.py deleted file mode 100644 index cb794938..00000000 --- a/api/glazierapi/db/migrate_repo/versions/002_add_session_table.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License.from oslo.config import cfg - -from sqlalchemy.schema import MetaData, Table, Column, ForeignKey -from sqlalchemy.types import String, Text, DateTime - -meta = MetaData() - -session = Table('session', meta, - Column('id', String(32), primary_key=True), - Column('environment_id', String(32), - ForeignKey('environment.id')), - Column('created', DateTime, nullable=False), - Column('updated', DateTime, nullable=False), - Column('user_id', String(32), nullable=False), - Column('state', Text(), nullable=False), - ) - - -def upgrade(migrate_engine): - meta.bind = migrate_engine - meta.reflect() - session.create() - - -def downgrade(migrate_engine): - meta.bind = migrate_engine - session.drop() diff --git a/api/glazierapi/db/migrate_repo/versions/003_add_status_table.py b/api/glazierapi/db/migrate_repo/versions/003_add_status_table.py deleted file mode 100644 index 135c0bcd..00000000 --- a/api/glazierapi/db/migrate_repo/versions/003_add_status_table.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License.from oslo.config import cfg - -from sqlalchemy.schema import MetaData, Table, Column, ForeignKey -from sqlalchemy.types import String, Text, DateTime - -meta = MetaData() - -status = Table('status', meta, - Column('id', String(32), primary_key=True), - Column('created', DateTime, nullable=False), - Column('updated', DateTime, nullable=False), - Column('entity', String(10), nullable=False), - Column('environment_id', String(32), - ForeignKey('environment.id')), - Column('session_id', String(32), ForeignKey('session.id')), - Column('text', Text(), nullable=False), - ) - - -def upgrade(migrate_engine): - meta.bind = migrate_engine - meta.reflect() - status.create() - - -def downgrade(migrate_engine): - meta.bind = migrate_engine - status.drop() diff --git a/api/glazierapi/db/migrate_repo/versions/004_add_description_column_to_session.py b/api/glazierapi/db/migrate_repo/versions/004_add_description_column_to_session.py deleted file mode 100644 index 27ff7c7d..00000000 --- a/api/glazierapi/db/migrate_repo/versions/004_add_description_column_to_session.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License.from oslo.config import cfg - -from sqlalchemy.schema import MetaData, Table, Column -from sqlalchemy.types import Text - -meta = MetaData() - - -def upgrade(migrate_engine): - meta.bind = migrate_engine - session = Table('session', meta, autoload=True) - description = Column('description', Text(), nullable=True, default='{}') - description.create(session) - - -def downgrade(migrate_engine): - meta.bind = migrate_engine - session = Table('session', meta, autoload=True) - session.c.description.drop() diff --git a/api/glazierapi/db/migrate_repo/versions/005_remove_obsolete_service_table.py b/api/glazierapi/db/migrate_repo/versions/005_remove_obsolete_service_table.py deleted file mode 100644 index 57be93da..00000000 --- a/api/glazierapi/db/migrate_repo/versions/005_remove_obsolete_service_table.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License.from oslo.config import cfg - -from sqlalchemy.schema import MetaData, Table, Column, ForeignKey -from sqlalchemy.types import String, Text, DateTime - - -meta = MetaData() - -service = Table('service', meta, - Column('id', String(32), primary_key=True), - Column('name', String(255), nullable=False), - Column('type', String(40), nullable=False), - Column('environment_id', String(32), - ForeignKey('environment.id')), - Column('created', DateTime, nullable=False), - Column('updated', DateTime, nullable=False), - Column('description', Text(), nullable=False), - ) - - -def upgrade(migrate_engine): - meta.bind = migrate_engine - meta.reflect() - service.drop() - - -def downgrade(migrate_engine): - meta.bind = migrate_engine - meta.reflect() - service.create() diff --git a/api/glazierapi/db/migrate_repo/versions/006_add_entity_id_column_to_status.py b/api/glazierapi/db/migrate_repo/versions/006_add_entity_id_column_to_status.py deleted file mode 100644 index 2e938d1c..00000000 --- a/api/glazierapi/db/migrate_repo/versions/006_add_entity_id_column_to_status.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License.from oslo.config import cfg - -from sqlalchemy.schema import MetaData, Table, Column -from sqlalchemy.types import String - -meta = MetaData() - - -def upgrade(migrate_engine): - meta.bind = migrate_engine - status = Table('status', meta, autoload=True) - entity_id = Column('entity_id', String(32), nullable=True) - entity_id.create(status) - - -def downgrade(migrate_engine): - meta.bind = migrate_engine - status = Table('status', meta, autoload=True) - status.c.entity_id.drop() diff --git a/api/glazierapi/db/migrate_repo/versions/__init__.py b/api/glazierapi/db/migrate_repo/versions/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/api/glazierapi/db/models.py b/api/glazierapi/db/models.py deleted file mode 100644 index ac373d23..00000000 --- a/api/glazierapi/db/models.py +++ /dev/null @@ -1,155 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -SQLAlchemy models for glazierapi data -""" -import anyjson - -from sqlalchemy import Column, String, BigInteger, TypeDecorator, ForeignKey -from sqlalchemy.ext.compiler import compiles -from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy import DateTime, Text -from sqlalchemy.orm import relationship, backref, object_mapper -from glazierapi.common import uuidutils - -from glazierapi.openstack.common import timeutils -from glazierapi.db.session import get_session - -BASE = declarative_base() - - -@compiles(BigInteger, 'sqlite') -def compile_big_int_sqlite(type_, compiler, **kw): - return 'INTEGER' - - -class ModelBase(object): - __protected_attributes__ = {"created", "updated"} - - created = Column(DateTime, default=timeutils.utcnow, - nullable=False) - updated = Column(DateTime, default=timeutils.utcnow, - nullable=False, onupdate=timeutils.utcnow) - - def save(self, session=None): - """Save this object""" - session = session or get_session() - session.add(self) - session.flush() - - def update(self, values): - """dict.update() behaviour.""" - for k, v in values.iteritems(): - self[k] = v - - def __setitem__(self, key, value): - setattr(self, key, value) - - def __getitem__(self, key): - return getattr(self, key) - - def __iter__(self): - self._i = iter(object_mapper(self).columns) - return self - - def next(self): - n = self._i.next().name - return n, getattr(self, n) - - def keys(self): - return self.__dict__.keys() - - def values(self): - return self.__dict__.values() - - def items(self): - return self.__dict__.items() - - def to_dict(self): - dictionary = self.__dict__.copy() - return {k: v for k, v in dictionary.iteritems() - if k != '_sa_instance_state'} - - -class JsonBlob(TypeDecorator): - impl = Text - - def process_bind_param(self, value, dialect): - return anyjson.serialize(value) - - def process_result_value(self, value, dialect): - return anyjson.deserialize(value) - - -class Environment(BASE, ModelBase): - """Represents a Environment in the metadata-store""" - __tablename__ = 'environment' - - id = Column(String(32), primary_key=True, default=uuidutils.generate_uuid) - name = Column(String(255), nullable=False) - tenant_id = Column(String(32), nullable=False) - description = Column(JsonBlob(), nullable=False, default='{}') - - def to_dict(self): - dictionary = super(Environment, self).to_dict() - del dictionary['description'] - return dictionary - - -class Session(BASE, ModelBase): - __tablename__ = 'session' - - id = Column(String(32), primary_key=True, default=uuidutils.generate_uuid) - environment_id = Column(String(32), ForeignKey('environment.id')) - environment = relationship(Environment, - backref=backref('session'), - uselist=False, lazy='joined') - user_id = Column(String(36), nullable=False) - state = Column(String(36), nullable=False) - description = Column(JsonBlob(), nullable=False) - - def to_dict(self): - dictionary = super(Session, self).to_dict() - del dictionary['description'] - return dictionary - - -class Status(BASE, ModelBase): - __tablename__ = 'status' - - id = Column(String(32), primary_key=True, default=uuidutils.generate_uuid) - entity_id = Column(String(32), nullable=False) - entity = Column(String(10), nullable=False) - environment_id = Column(String(32), ForeignKey('environment.id')) - session_id = Column(String(32), ForeignKey('session.id')) - text = Column(Text(), nullable=False) - - -def register_models(engine): - """ - Creates database tables for all models with the given engine - """ - models = (Environment, Status, Session) - for model in models: - model.metadata.create_all(engine) - - -def unregister_models(engine): - """ - Drops database tables for all models with the given engine - """ - models = (Environment, Status, Session) - for model in models: - model.metadata.drop_all(engine) diff --git a/api/glazierapi/db/session.py b/api/glazierapi/db/session.py deleted file mode 100644 index 2d94b973..00000000 --- a/api/glazierapi/db/session.py +++ /dev/null @@ -1,110 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright (c) 2011 X.commerce, a business unit of eBay Inc. -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# Copyright 2011 Piston Cloud Computing, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -"""Session management functions.""" - -import os -import logging - -from migrate.versioning import api as versioning_api -from migrate import exceptions as versioning_exceptions -from sqlalchemy import create_engine -from sqlalchemy.engine.url import make_url -from sqlalchemy.orm import sessionmaker -from sqlalchemy.pool import NullPool -from sqlalchemy.exc import DisconnectionError - -from glazierapi.common.config import CONF as conf - -from glazierapi.db import migrate_repo - - -MAKER = None -ENGINE = None - - -class MySQLPingListener(object): - """ - Ensures that MySQL connections checked out of the - pool are alive. - - Borrowed from: - http://groups.google.com/group/sqlalchemy/msg/a4ce563d802c929f - - Error codes caught: - * 2006 MySQL server has gone away - * 2013 Lost connection to MySQL server during query - * 2014 Commands out of sync; you can't run this command now - * 2045 Can't open shared memory; no answer from server (%lu) - * 2055 Lost connection to MySQL server at '%s', system error: %d - - from http://dev.mysql.com/doc/refman/5.6/ru_RU/error-messages-client.html - """ - - def checkout(self, dbapi_con, con_record, con_proxy): - try: - dbapi_con.cursor().execute('select 1') - except dbapi_con.OperationalError, ex: - if ex.args[0] in (2006, 2013, 2014, 2045, 2055): - logging.warn('Got mysql server has gone away: %s', ex) - raise DisconnectionError("Database server went away") - else: - raise - - -def get_session(autocommit=True, expire_on_commit=False): - """Return a SQLAlchemy session.""" - global MAKER - - if MAKER is None: - MAKER = sessionmaker(autocommit=autocommit, - expire_on_commit=expire_on_commit) - engine = get_engine() - MAKER.configure(bind=engine) - session = MAKER() - return session - - -def get_engine(): - """Return a SQLAlchemy engine.""" - global ENGINE - - connection_url = make_url(conf.sql_connection) - if ENGINE is None or not ENGINE.url == connection_url: - engine_args = {'pool_recycle': 3600, - 'echo': False, - 'convert_unicode': True - } - if 'sqlite' in connection_url.drivername: - engine_args['poolclass'] = NullPool - if 'mysql' in connection_url.drivername: - engine_args['listeners'] = [MySQLPingListener()] - ENGINE = create_engine(conf.sql_connection, **engine_args) - - sync() - return ENGINE - - -def sync(): - repo_path = os.path.abspath(os.path.dirname(migrate_repo.__file__)) - try: - versioning_api.upgrade(conf.sql_connection, repo_path) - except versioning_exceptions.DatabaseNotControlledError: - versioning_api.version_control(conf.sql_connection, repo_path) - versioning_api.upgrade(conf.sql_connection, repo_path) diff --git a/api/glazierapi/locale/ru/LC_MESSAGES/glazierapi.po b/api/glazierapi/locale/ru/LC_MESSAGES/glazierapi.po deleted file mode 100644 index 4ff98950..00000000 --- a/api/glazierapi/locale/ru/LC_MESSAGES/glazierapi.po +++ /dev/null @@ -1,191 +0,0 @@ -# Russian translations for PROJECT. -# Copyright (C) 2012 ORGANIZATION -# This file is distributed under the same license as the PROJECT project. -# FIRST AUTHOR <EMAIL@ADDRESS>, 2012. -# -msgid "" -msgstr "" -"Project-Id-Version: PROJECT VERSION\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2013-03-01 17:33+0400\n" -"PO-Revision-Date: 2012-04-26 17:40+0800\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -"Language-Team: ru <LL@li.org>\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " -"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 0.9.6\n" - -#: portas/exefile.py:2 -msgid "Hello" -msgstr "Привет!" - -#: portas/openstack/common/exception.py:104 -msgid "Uncaught exception" -msgstr "" - -#: portas/openstack/common/jsonutils.py:88 -#, python-format -msgid "Max serialization depth exceeded on object: %d %s" -msgstr "" - -#: portas/openstack/common/log.py:225 -#, python-format -msgid "Deprecated: %s" -msgstr "" - -#: portas/openstack/common/log.py:358 -#, python-format -msgid "syslog facility must be one of: %s" -msgstr "" - -#: portas/openstack/common/log.py:518 -#, python-format -msgid "Fatal call to deprecated config: %(msg)s" -msgstr "" - -#: portas/openstack/common/service.py:112 -#: portas/openstack/common/service.py:275 -msgid "Full set of CONF:" -msgstr "" - -#: portas/openstack/common/service.py:121 -#: portas/openstack/common/service.py:218 -#, python-format -msgid "Caught %s, exiting" -msgstr "" - -#: portas/openstack/common/service.py:164 -msgid "Parent process has died unexpectedly, exiting" -msgstr "" - -#: portas/openstack/common/service.py:200 -msgid "Forking too fast, sleeping" -msgstr "" - -#: portas/openstack/common/service.py:223 -msgid "Unhandled exception" -msgstr "" - -#: portas/openstack/common/service.py:230 -#, python-format -msgid "Started child %d" -msgstr "" - -#: portas/openstack/common/service.py:240 -#, python-format -msgid "Starting %d workers" -msgstr "" - -#: portas/openstack/common/service.py:257 -#, python-format -msgid "Child %(pid)d killed by signal %(sig)d" -msgstr "" - -#: portas/openstack/common/service.py:261 -#, python-format -msgid "Child %(pid)s exited with status %(code)d" -msgstr "" - -#: portas/openstack/common/service.py:265 -#, python-format -msgid "pid %d not in child list" -msgstr "" - -#: portas/openstack/common/service.py:293 -#, python-format -msgid "Caught %s, stopping children" -msgstr "" - -#: portas/openstack/common/service.py:304 -#, python-format -msgid "Waiting on %d children to exit" -msgstr "" - -#: portas/openstack/common/sslutils.py:52 -#, python-format -msgid "Unable to find cert_file : %s" -msgstr "" - -#: portas/openstack/common/sslutils.py:55 -#, python-format -msgid "Unable to find ca_file : %s" -msgstr "" - -#: portas/openstack/common/sslutils.py:58 -#, python-format -msgid "Unable to find key_file : %s" -msgstr "" - -#: portas/openstack/common/sslutils.py:61 -msgid "" -"When running server in SSL mode, you must specify both a cert_file and " -"key_file option value in your configuration file" -msgstr "" - -#: portas/openstack/common/wsgi.py:110 -#, python-format -msgid "Could not bind to %(host)s:%(port)s after trying for 30 seconds" -msgstr "" - -#: portas/openstack/common/wsgi.py:372 -msgid "Unsupported Content-Type" -msgstr "" - -#: portas/openstack/common/wsgi.py:375 -msgid "Malformed request body" -msgstr "" - -#: portas/openstack/common/wsgi.py:660 -msgid "Empty body provided in request" -msgstr "" - -#: portas/openstack/common/wsgi.py:666 -msgid "Unrecognized Content-Type provided in request" -msgstr "" - -#: portas/openstack/common/wsgi.py:670 -msgid "No Content-Type provided in request" -msgstr "" - -#: portas/openstack/common/wsgi.py:676 -msgid "Unable to deserialize body as provided Content-Type" -msgstr "" - -#: portas/openstack/common/wsgi.py:726 -msgid "cannot understand JSON" -msgstr "" - -#: portas/openstack/common/wsgi.py:750 -msgid "cannot understand XML" -msgstr "" - -#: portas/openstack/common/notifier/api.py:126 -#, python-format -msgid "%s not in valid priorities" -msgstr "" - -#: portas/openstack/common/notifier/api.py:142 -#, python-format -msgid "" -"Problem '%(e)s' attempting to send to notification system. " -"Payload=%(payload)s" -msgstr "" - -#: portas/openstack/common/notifier/api.py:172 -#, python-format -msgid "Failed to load notifier %s. These notifications will not be sent." -msgstr "" - -#: portas/openstack/common/notifier/rabbit_notifier.py:27 -msgid "The rabbit_notifier is now deprecated. Please use rpc_notifier instead." -msgstr "" - -#: portas/openstack/common/notifier/rpc_notifier.py:45 -#: portas/openstack/common/notifier/rpc_notifier2.py:51 -#, python-format -msgid "Could not send notification to %(topic)s. Payload=%(message)s" -msgstr "" - diff --git a/api/glazierapi/openstack/__init__.py b/api/glazierapi/openstack/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/api/glazierapi/openstack/common/__init__.py b/api/glazierapi/openstack/common/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/api/glazierapi/openstack/common/eventlet_backdoor.py b/api/glazierapi/openstack/common/eventlet_backdoor.py deleted file mode 100644 index 8b81ebf8..00000000 --- a/api/glazierapi/openstack/common/eventlet_backdoor.py +++ /dev/null @@ -1,87 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright (c) 2012 Openstack, LLC. -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import gc -import pprint -import sys -import traceback - -import eventlet -import eventlet.backdoor -import greenlet -from oslo.config import cfg - -eventlet_backdoor_opts = [ - cfg.IntOpt('backdoor_port', - default=None, - help='port for eventlet backdoor to listen') -] - -CONF = cfg.CONF -CONF.register_opts(eventlet_backdoor_opts) - - -def _dont_use_this(): - print "Don't use this, just disconnect instead" - - -def _find_objects(t): - return filter(lambda o: isinstance(o, t), gc.get_objects()) - - -def _print_greenthreads(): - for i, gt in enumerate(_find_objects(greenlet.greenlet)): - print i, gt - traceback.print_stack(gt.gr_frame) - print - - -def _print_nativethreads(): - for threadId, stack in sys._current_frames().items(): - print threadId - traceback.print_stack(stack) - print - - -def initialize_if_enabled(): - backdoor_locals = { - 'exit': _dont_use_this, # So we don't exit the entire process - 'quit': _dont_use_this, # So we don't exit the entire process - 'fo': _find_objects, - 'pgt': _print_greenthreads, - 'pnt': _print_nativethreads, - } - - if CONF.backdoor_port is None: - return None - - # NOTE(johannes): The standard sys.displayhook will print the value of - # the last expression and set it to __builtin__._, which overwrites - # the __builtin__._ that gettext sets. Let's switch to using pprint - # since it won't interact poorly with gettext, and it's easier to - # read the output too. - def displayhook(val): - if val is not None: - pprint.pprint(val) - sys.displayhook = displayhook - - sock = eventlet.listen(('localhost', CONF.backdoor_port)) - port = sock.getsockname()[1] - eventlet.spawn_n(eventlet.backdoor.backdoor_server, sock, - locals=backdoor_locals) - return port diff --git a/api/glazierapi/openstack/common/exception.py b/api/glazierapi/openstack/common/exception.py deleted file mode 100644 index 02dffa4d..00000000 --- a/api/glazierapi/openstack/common/exception.py +++ /dev/null @@ -1,142 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Exceptions common to OpenStack projects -""" - -import logging - -from glazierapi.openstack.common.gettextutils import _ - -_FATAL_EXCEPTION_FORMAT_ERRORS = False - - -class Error(Exception): - def __init__(self, message=None): - super(Error, self).__init__(message) - - -class ApiError(Error): - def __init__(self, message='Unknown', code='Unknown'): - self.message = message - self.code = code - super(ApiError, self).__init__('%s: %s' % (code, message)) - - -class NotFound(Error): - pass - - -class UnknownScheme(Error): - - msg = "Unknown scheme '%s' found in URI" - - def __init__(self, scheme): - msg = self.__class__.msg % scheme - super(UnknownScheme, self).__init__(msg) - - -class BadStoreUri(Error): - - msg = "The Store URI %s was malformed. Reason: %s" - - def __init__(self, uri, reason): - msg = self.__class__.msg % (uri, reason) - super(BadStoreUri, self).__init__(msg) - - -class Duplicate(Error): - pass - - -class NotAuthorized(Error): - pass - - -class NotEmpty(Error): - pass - - -class Invalid(Error): - pass - - -class BadInputError(Exception): - """Error resulting from a client sending bad input to a server""" - pass - - -class MissingArgumentError(Error): - pass - - -class DatabaseMigrationError(Error): - pass - - -class ClientConnectionError(Exception): - """Error resulting from a client connecting to a server""" - pass - - -def wrap_exception(f): - def _wrap(*args, **kw): - try: - return f(*args, **kw) - except Exception, e: - if not isinstance(e, Error): - #exc_type, exc_value, exc_traceback = sys.exc_info() - logging.exception(_('Uncaught exception')) - #logging.error(traceback.extract_stack(exc_traceback)) - raise Error(str(e)) - raise - _wrap.func_name = f.func_name - return _wrap - - -class OpenstackException(Exception): - """ - Base Exception - - To correctly use this class, inherit from it and define - a 'message' property. That message will get printf'd - with the keyword arguments provided to the constructor. - """ - message = "An unknown exception occurred" - - def __init__(self, **kwargs): - try: - self._error_string = self.message % kwargs - - except Exception as e: - if _FATAL_EXCEPTION_FORMAT_ERRORS: - raise e - else: - # at least get the core message out if something happened - self._error_string = self.message - - def __str__(self): - return self._error_string - - -class MalformedRequestBody(OpenstackException): - message = "Malformed message body: %(reason)s" - - -class InvalidContentType(OpenstackException): - message = "Invalid content type %(content_type)s" diff --git a/api/glazierapi/openstack/common/gettextutils.py b/api/glazierapi/openstack/common/gettextutils.py deleted file mode 100644 index fb1a1b7b..00000000 --- a/api/glazierapi/openstack/common/gettextutils.py +++ /dev/null @@ -1,33 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -gettext for openstack-common modules. - -Usual usage in an openstack.common module: - - from glazierapi.openstack.common.gettextutils import _ -""" - -import gettext - - -t = gettext.translation('openstack-common', 'locale', fallback=True) - - -def _(msg): - return t.ugettext(msg) diff --git a/api/glazierapi/openstack/common/importutils.py b/api/glazierapi/openstack/common/importutils.py deleted file mode 100644 index 9dec764f..00000000 --- a/api/glazierapi/openstack/common/importutils.py +++ /dev/null @@ -1,67 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Import related utilities and helper functions. -""" - -import sys -import traceback - - -def import_class(import_str): - """Returns a class from a string including module and class""" - mod_str, _sep, class_str = import_str.rpartition('.') - try: - __import__(mod_str) - return getattr(sys.modules[mod_str], class_str) - except (ValueError, AttributeError): - raise ImportError('Class %s cannot be found (%s)' % - (class_str, - traceback.format_exception(*sys.exc_info()))) - - -def import_object(import_str, *args, **kwargs): - """Import a class and return an instance of it.""" - return import_class(import_str)(*args, **kwargs) - - -def import_object_ns(name_space, import_str, *args, **kwargs): - """ - Import a class and return an instance of it, first by trying - to find the class in a default namespace, then failing back to - a full path if not found in the default namespace. - """ - import_value = "%s.%s" % (name_space, import_str) - try: - return import_class(import_value)(*args, **kwargs) - except ImportError: - return import_class(import_str)(*args, **kwargs) - - -def import_module(import_str): - """Import a module.""" - __import__(import_str) - return sys.modules[import_str] - - -def try_import(import_str, default=None): - """Try to import a module and if it fails return default.""" - try: - return import_module(import_str) - except ImportError: - return default diff --git a/api/glazierapi/openstack/common/jsonutils.py b/api/glazierapi/openstack/common/jsonutils.py deleted file mode 100644 index 4ef48ea6..00000000 --- a/api/glazierapi/openstack/common/jsonutils.py +++ /dev/null @@ -1,147 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# Copyright 2011 Justin Santa Barbara -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -''' -JSON related utilities. - -This module provides a few things: - - 1) A handy function for getting an object down to something that can be - JSON serialized. See to_primitive(). - - 2) Wrappers around loads() and dumps(). The dumps() wrapper will - automatically use to_primitive() for you if needed. - - 3) This sets up anyjson to use the loads() and dumps() wrappers if anyjson - is available. -''' - - -import datetime -import functools -import inspect -import itertools -import json -import logging -import xmlrpclib - -from glazierapi.openstack.common.gettextutils import _ -from glazierapi.openstack.common import timeutils - -LOG = logging.getLogger(__name__) - - -def to_primitive(value, convert_instances=False, convert_datetime=True, - level=0, max_depth=3): - """Convert a complex object into primitives. - - Handy for JSON serialization. We can optionally handle instances, - but since this is a recursive function, we could have cyclical - data structures. - - To handle cyclical data structures we could track the actual objects - visited in a set, but not all objects are hashable. Instead we just - track the depth of the object inspections and don't go too deep. - - Therefore, convert_instances=True is lossy ... be aware. - - """ - nasty = [inspect.ismodule, inspect.isclass, inspect.ismethod, - inspect.isfunction, inspect.isgeneratorfunction, - inspect.isgenerator, inspect.istraceback, inspect.isframe, - inspect.iscode, inspect.isbuiltin, inspect.isroutine, - inspect.isabstract] - for test in nasty: - if test(value): - return unicode(value) - - # value of itertools.count doesn't get caught by inspects - # above and results in infinite loop when list(value) is called. - if type(value) == itertools.count: - return unicode(value) - - # FIXME(vish): Workaround for LP bug 852095. Without this workaround, - # tests that raise an exception in a mocked method that - # has a @wrap_exception with a notifier will fail. If - # we up the dependency to 0.5.4 (when it is released) we - # can remove this workaround. - if getattr(value, '__module__', None) == 'mox': - return 'mock' - - if level > max_depth: - LOG.error(_('Max serialization depth exceeded on object: %d %s'), - level, value) - return '?' - - # The try block may not be necessary after the class check above, - # but just in case ... - try: - recursive = functools.partial(to_primitive, - convert_instances=convert_instances, - convert_datetime=convert_datetime, - level=level, - max_depth=max_depth) - # It's not clear why xmlrpclib created their own DateTime type, but - # for our purposes, make it a datetime type which is explicitly - # handled - if isinstance(value, xmlrpclib.DateTime): - value = datetime.datetime(*tuple(value.timetuple())[:6]) - - if isinstance(value, (list, tuple)): - return [recursive(v) for v in value] - elif isinstance(value, dict): - return dict((k, recursive(v)) for k, v in value.iteritems()) - elif convert_datetime and isinstance(value, datetime.datetime): - return timeutils.strtime(value) - elif hasattr(value, 'iteritems'): - return recursive(dict(value.iteritems()), level=level + 1) - elif hasattr(value, '__iter__'): - return recursive(list(value)) - elif convert_instances and hasattr(value, '__dict__'): - # Likely an instance of something. Watch for cycles. - # Ignore class member vars. - return recursive(value.__dict__, level=level + 1) - else: - return value - except TypeError: - # Class objects are tricky since they may define something like - # __iter__ defined but it isn't callable as list(). - return unicode(value) - - -def dumps(value, default=to_primitive, **kwargs): - return json.dumps(value, default=default, **kwargs) - - -def loads(s): - return json.loads(s) - - -def load(s): - return json.load(s) - - -try: - import anyjson -except ImportError: - pass -else: - anyjson._modules.append((__name__, 'dumps', TypeError, - 'loads', ValueError, 'load')) - anyjson.force_implementation(__name__) diff --git a/api/glazierapi/openstack/common/local.py b/api/glazierapi/openstack/common/local.py deleted file mode 100644 index 8bdc837a..00000000 --- a/api/glazierapi/openstack/common/local.py +++ /dev/null @@ -1,48 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Greenthread local storage of variables using weak references""" - -import weakref - -from eventlet import corolocal - - -class WeakLocal(corolocal.local): - def __getattribute__(self, attr): - rval = corolocal.local.__getattribute__(self, attr) - if rval: - # NOTE(mikal): this bit is confusing. What is stored is a weak - # reference, not the value itself. We therefore need to lookup - # the weak reference and return the inner value here. - rval = rval() - return rval - - def __setattr__(self, attr, value): - value = weakref.ref(value) - return corolocal.local.__setattr__(self, attr, value) - - -# NOTE(mikal): the name "store" should be deprecated in the future -store = WeakLocal() - -# A "weak" store uses weak references and allows an object to fall out of scope -# when it falls out of scope in the code that uses the thread local storage. A -# "strong" store will hold a reference to the object so that it never falls out -# of scope. -weak_store = WeakLocal() -strong_store = corolocal.local diff --git a/api/glazierapi/openstack/common/log.py b/api/glazierapi/openstack/common/log.py deleted file mode 100644 index e8caddb9..00000000 --- a/api/glazierapi/openstack/common/log.py +++ /dev/null @@ -1,521 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack LLC. -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Openstack logging handler. - -This module adds to logging functionality by adding the option to specify -a context object when calling the various log methods. If the context object -is not specified, default formatting is used. Additionally, an instance uuid -may be passed as part of the log message, which is intended to make it easier -for admins to find messages related to a specific instance. - -It also allows setting of formatting information through conf. - -""" - -import cStringIO -import inspect -import itertools -import logging -import logging.config -import logging.handlers -import os -import stat -import sys -import traceback - -from oslo.config import cfg - -from glazierapi.openstack.common.gettextutils import _ -from glazierapi.openstack.common import jsonutils -from glazierapi.openstack.common import local -from glazierapi.openstack.common import notifier - - -_DEFAULT_LOG_FORMAT = "%(asctime)s %(levelname)8s [%(name)s] %(message)s" -_DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S" - -common_cli_opts = [ - cfg.BoolOpt('debug', - short='d', - default=False, - help='Print debugging output (set logging level to ' - 'DEBUG instead of default WARNING level).'), - cfg.BoolOpt('verbose', - short='v', - default=False, - help='Print more verbose output (set logging level to ' - 'INFO instead of default WARNING level).'), -] - -logging_cli_opts = [ - cfg.StrOpt('log-config', - metavar='PATH', - help='If this option is specified, the logging configuration ' - 'file specified is used and overrides any other logging ' - 'options specified. Please see the Python logging module ' - 'documentation for details on logging configuration ' - 'files.'), - cfg.StrOpt('log-format', - default=_DEFAULT_LOG_FORMAT, - metavar='FORMAT', - help='A logging.Formatter log message format string which may ' - 'use any of the available logging.LogRecord attributes. ' - 'Default: %(default)s'), - cfg.StrOpt('log-date-format', - default=_DEFAULT_LOG_DATE_FORMAT, - metavar='DATE_FORMAT', - help='Format string for %%(asctime)s in log records. ' - 'Default: %(default)s'), - cfg.StrOpt('log-file', - metavar='PATH', - deprecated_name='logfile', - help='(Optional) Name of log file to output to. ' - 'If not set, logging will go to stdout.'), - cfg.StrOpt('log-dir', - deprecated_name='logdir', - help='(Optional) The directory to keep log files in ' - '(will be prepended to --log-file)'), - cfg.BoolOpt('use-syslog', - default=False, - help='Use syslog for logging.'), - cfg.StrOpt('syslog-log-facility', - default='LOG_USER', - help='syslog facility to receive log lines') -] - -generic_log_opts = [ - cfg.BoolOpt('use_stderr', - default=True, - help='Log output to standard error'), - cfg.StrOpt('logfile_mode', - default='0644', - help='Default file mode used when creating log files'), -] - -log_opts = [ - cfg.StrOpt('logging_context_format_string', - default='%(asctime)s.%(msecs)03d %(levelname)s %(name)s ' - '[%(request_id)s %(user)s %(tenant)s] %(instance)s' - '%(message)s', - help='format string to use for log messages with context'), - cfg.StrOpt('logging_default_format_string', - default='%(asctime)s.%(msecs)03d %(process)d %(levelname)s ' - '%(name)s [-] %(instance)s%(message)s', - help='format string to use for log messages without context'), - cfg.StrOpt('logging_debug_format_suffix', - default='%(funcName)s %(pathname)s:%(lineno)d', - help='data to append to log format when level is DEBUG'), - cfg.StrOpt('logging_exception_prefix', - default='%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s ' - '%(instance)s', - help='prefix each line of exception output with this format'), - cfg.ListOpt('default_log_levels', - default=[ - 'amqplib=WARN', - 'sqlalchemy=WARN', - 'boto=WARN', - 'suds=INFO', - 'keystone=INFO', - 'eventlet.wsgi.server=WARN' - ], - help='list of logger=LEVEL pairs'), - cfg.BoolOpt('publish_errors', - default=False, - help='publish error events'), - cfg.BoolOpt('fatal_deprecations', - default=False, - help='make deprecations fatal'), - - # NOTE(mikal): there are two options here because sometimes we are handed - # a full instance (and could include more information), and other times we - # are just handed a UUID for the instance. - cfg.StrOpt('instance_format', - default='[instance: %(uuid)s] ', - help='If an instance is passed with the log message, format ' - 'it like this'), - cfg.StrOpt('instance_uuid_format', - default='[instance: %(uuid)s] ', - help='If an instance UUID is passed with the log message, ' - 'format it like this'), -] - -CONF = cfg.CONF -CONF.register_cli_opts(common_cli_opts) -CONF.register_cli_opts(logging_cli_opts) -CONF.register_opts(generic_log_opts) -CONF.register_opts(log_opts) - -# our new audit level -# NOTE(jkoelker) Since we synthesized an audit level, make the logging -# module aware of it so it acts like other levels. -logging.AUDIT = logging.INFO + 1 -logging.addLevelName(logging.AUDIT, 'AUDIT') - - -try: - NullHandler = logging.NullHandler -except AttributeError: # NOTE(jkoelker) NullHandler added in Python 2.7 - class NullHandler(logging.Handler): - def handle(self, record): - pass - - def emit(self, record): - pass - - def createLock(self): - self.lock = None - - -def _dictify_context(context): - if context is None: - return None - if not isinstance(context, dict) and getattr(context, 'to_dict', None): - context = context.to_dict() - return context - - -def _get_binary_name(): - return os.path.basename(inspect.stack()[-1][1]) - - -def _get_log_file_path(binary=None): - logfile = CONF.log_file - logdir = CONF.log_dir - - if logfile and not logdir: - return logfile - - if logfile and logdir: - return os.path.join(logdir, logfile) - - if logdir: - binary = binary or _get_binary_name() - return '%s.log' % (os.path.join(logdir, binary),) - - -class ContextAdapter(logging.LoggerAdapter): - warn = logging.LoggerAdapter.warning - - def __init__(self, logger, project_name, version_string): - self.logger = logger - self.project = project_name - self.version = version_string - - def audit(self, msg, *args, **kwargs): - self.log(logging.AUDIT, msg, *args, **kwargs) - - def deprecated(self, msg, *args, **kwargs): - stdmsg = _("Deprecated: %s") % msg - if CONF.fatal_deprecations: - self.critical(stdmsg, *args, **kwargs) - raise DeprecatedConfig(msg=stdmsg) - else: - self.warn(stdmsg, *args, **kwargs) - - def process(self, msg, kwargs): - if 'extra' not in kwargs: - kwargs['extra'] = {} - extra = kwargs['extra'] - - context = kwargs.pop('context', None) - if not context: - context = getattr(local.store, 'context', None) - if context: - extra.update(_dictify_context(context)) - - instance = kwargs.pop('instance', None) - instance_extra = '' - if instance: - instance_extra = CONF.instance_format % instance - else: - instance_uuid = kwargs.pop('instance_uuid', None) - if instance_uuid: - instance_extra = (CONF.instance_uuid_format - % {'uuid': instance_uuid}) - extra.update({'instance': instance_extra}) - - extra.update({"project": self.project}) - extra.update({"version": self.version}) - extra['extra'] = extra.copy() - return msg, kwargs - - -class JSONFormatter(logging.Formatter): - def __init__(self, fmt=None, datefmt=None): - # NOTE(jkoelker) we ignore the fmt argument, but its still there - # since logging.config.fileConfig passes it. - self.datefmt = datefmt - - def formatException(self, ei, strip_newlines=True): - lines = traceback.format_exception(*ei) - if strip_newlines: - lines = [itertools.ifilter( - lambda x: x, - line.rstrip().splitlines()) for line in lines] - lines = list(itertools.chain(*lines)) - return lines - - def format(self, record): - message = {'message': record.getMessage(), - 'asctime': self.formatTime(record, self.datefmt), - 'name': record.name, - 'msg': record.msg, - 'args': record.args, - 'levelname': record.levelname, - 'levelno': record.levelno, - 'pathname': record.pathname, - 'filename': record.filename, - 'module': record.module, - 'lineno': record.lineno, - 'funcname': record.funcName, - 'created': record.created, - 'msecs': record.msecs, - 'relative_created': record.relativeCreated, - 'thread': record.thread, - 'thread_name': record.threadName, - 'process_name': record.processName, - 'process': record.process, - 'traceback': None} - - if hasattr(record, 'extra'): - message['extra'] = record.extra - - if record.exc_info: - message['traceback'] = self.formatException(record.exc_info) - - return jsonutils.dumps(message) - - -class PublishErrorsHandler(logging.Handler): - def emit(self, record): - if ('glazierapi.openstack.common.notifier.log_notifier' in - CONF.notification_driver): - return - notifier.api.notify(None, 'error.publisher', - 'error_notification', - notifier.api.ERROR, - dict(error=record.msg)) - - -def _create_logging_excepthook(product_name): - def logging_excepthook(type, value, tb): - extra = {} - if CONF.verbose: - extra['exc_info'] = (type, value, tb) - getLogger(product_name).critical(str(value), **extra) - return logging_excepthook - - -def setup(product_name): - """Setup logging.""" - if CONF.log_config: - logging.config.fileConfig(CONF.log_config) - else: - _setup_logging_from_conf(product_name) - sys.excepthook = _create_logging_excepthook(product_name) - - -def set_defaults(logging_context_format_string): - cfg.set_defaults(log_opts, - logging_context_format_string= - logging_context_format_string) - - -def _find_facility_from_conf(): - facility_names = logging.handlers.SysLogHandler.facility_names - facility = getattr(logging.handlers.SysLogHandler, - CONF.syslog_log_facility, - None) - - if facility is None and CONF.syslog_log_facility in facility_names: - facility = facility_names.get(CONF.syslog_log_facility) - - if facility is None: - valid_facilities = facility_names.keys() - consts = ['LOG_AUTH', 'LOG_AUTHPRIV', 'LOG_CRON', 'LOG_DAEMON', - 'LOG_FTP', 'LOG_KERN', 'LOG_LPR', 'LOG_MAIL', 'LOG_NEWS', - 'LOG_AUTH', 'LOG_SYSLOG', 'LOG_USER', 'LOG_UUCP', - 'LOG_LOCAL0', 'LOG_LOCAL1', 'LOG_LOCAL2', 'LOG_LOCAL3', - 'LOG_LOCAL4', 'LOG_LOCAL5', 'LOG_LOCAL6', 'LOG_LOCAL7'] - valid_facilities.extend(consts) - raise TypeError(_('syslog facility must be one of: %s') % - ', '.join("'%s'" % fac - for fac in valid_facilities)) - - return facility - - -def _setup_logging_from_conf(product_name): - log_root = getLogger(product_name).logger - for handler in log_root.handlers: - log_root.removeHandler(handler) - - if CONF.use_syslog: - facility = _find_facility_from_conf() - syslog = logging.handlers.SysLogHandler(address='/dev/log', - facility=facility) - log_root.addHandler(syslog) - - logpath = _get_log_file_path() - if logpath: - filelog = logging.handlers.WatchedFileHandler(logpath) - log_root.addHandler(filelog) - - mode = int(CONF.logfile_mode, 8) - st = os.stat(logpath) - if st.st_mode != (stat.S_IFREG | mode): - os.chmod(logpath, mode) - - if CONF.use_stderr: - streamlog = ColorHandler() - log_root.addHandler(streamlog) - - elif not CONF.log_file: - # pass sys.stdout as a positional argument - # python2.6 calls the argument strm, in 2.7 it's stream - streamlog = logging.StreamHandler(sys.stdout) - log_root.addHandler(streamlog) - - if CONF.publish_errors: - log_root.addHandler(PublishErrorsHandler(logging.ERROR)) - - for handler in log_root.handlers: - datefmt = CONF.log_date_format - if CONF.log_format: - handler.setFormatter(logging.Formatter(fmt=CONF.log_format, - datefmt=datefmt)) - handler.setFormatter(LegacyFormatter(datefmt=datefmt)) - - if CONF.debug: - log_root.setLevel(logging.DEBUG) - elif CONF.verbose: - log_root.setLevel(logging.INFO) - else: - log_root.setLevel(logging.WARNING) - - level = logging.NOTSET - for pair in CONF.default_log_levels: - mod, _sep, level_name = pair.partition('=') - level = logging.getLevelName(level_name) - logger = logging.getLogger(mod) - logger.setLevel(level) - for handler in log_root.handlers: - logger.addHandler(handler) - -_loggers = {} - - -def getLogger(name='unknown', version='unknown'): - if name not in _loggers: - _loggers[name] = ContextAdapter(logging.getLogger(name), - name, - version) - return _loggers[name] - - -class WritableLogger(object): - """A thin wrapper that responds to `write` and logs.""" - - def __init__(self, logger, level=logging.INFO): - self.logger = logger - self.level = level - - def write(self, msg): - self.logger.log(self.level, msg) - - -class LegacyFormatter(logging.Formatter): - """A context.RequestContext aware formatter configured through flags. - - The flags used to set format strings are: logging_context_format_string - and logging_default_format_string. You can also specify - logging_debug_format_suffix to append extra formatting if the log level is - debug. - - For information about what variables are available for the formatter see: - http://docs.python.org/library/logging.html#formatter - - """ - - def format(self, record): - """Uses contextstring if request_id is set, otherwise default.""" - # NOTE(sdague): default the fancier formating params - # to an empty string so we don't throw an exception if - # they get used - for key in ('instance', 'color'): - if key not in record.__dict__: - record.__dict__[key] = '' - - if record.__dict__.get('request_id', None): - self._fmt = CONF.logging_context_format_string - else: - self._fmt = CONF.logging_default_format_string - - if (record.levelno == logging.DEBUG and - CONF.logging_debug_format_suffix): - self._fmt += " " + CONF.logging_debug_format_suffix - - # Cache this on the record, Logger will respect our formated copy - if record.exc_info: - record.exc_text = self.formatException(record.exc_info, record) - return logging.Formatter.format(self, record) - - def formatException(self, exc_info, record=None): - """Format exception output with CONF.logging_exception_prefix.""" - if not record: - return logging.Formatter.formatException(self, exc_info) - - stringbuffer = cStringIO.StringIO() - traceback.print_exception(exc_info[0], exc_info[1], exc_info[2], - None, stringbuffer) - lines = stringbuffer.getvalue().split('\n') - stringbuffer.close() - - if CONF.logging_exception_prefix.find('%(asctime)') != -1: - record.asctime = self.formatTime(record, self.datefmt) - - formatted_lines = [] - for line in lines: - pl = CONF.logging_exception_prefix % record.__dict__ - fl = '%s%s' % (pl, line) - formatted_lines.append(fl) - return '\n'.join(formatted_lines) - - -class ColorHandler(logging.StreamHandler): - LEVEL_COLORS = { - logging.DEBUG: '\033[00;32m', # GREEN - logging.INFO: '\033[00;36m', # CYAN - logging.AUDIT: '\033[01;36m', # BOLD CYAN - logging.WARN: '\033[01;33m', # BOLD YELLOW - logging.ERROR: '\033[01;31m', # BOLD RED - logging.CRITICAL: '\033[01;31m', # BOLD RED - } - - def format(self, record): - record.color = self.LEVEL_COLORS[record.levelno] - return logging.StreamHandler.format(self, record) - - -class DeprecatedConfig(Exception): - message = _("Fatal call to deprecated config: %(msg)s") - - def __init__(self, msg): - super(Exception, self).__init__(self.message % dict(msg=msg)) diff --git a/api/glazierapi/openstack/common/loopingcall.py b/api/glazierapi/openstack/common/loopingcall.py deleted file mode 100644 index 02420da4..00000000 --- a/api/glazierapi/openstack/common/loopingcall.py +++ /dev/null @@ -1,95 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# Copyright 2011 Justin Santa Barbara -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import sys - -from eventlet import event -from eventlet import greenthread - -from glazierapi.openstack.common.gettextutils import _ -from glazierapi.openstack.common import log as logging -from glazierapi.openstack.common import timeutils - -LOG = logging.getLogger(__name__) - - -class LoopingCallDone(Exception): - """Exception to break out and stop a LoopingCall. - - The poll-function passed to LoopingCall can raise this exception to - break out of the loop normally. This is somewhat analogous to - StopIteration. - - An optional return-value can be included as the argument to the exception; - this return-value will be returned by LoopingCall.wait() - - """ - - def __init__(self, retvalue=True): - """:param retvalue: Value that LoopingCall.wait() should return.""" - self.retvalue = retvalue - - -class LoopingCall(object): - def __init__(self, f=None, *args, **kw): - self.args = args - self.kw = kw - self.f = f - self._running = False - - def start(self, interval, initial_delay=None): - self._running = True - done = event.Event() - - def _inner(): - if initial_delay: - greenthread.sleep(initial_delay) - - try: - while self._running: - start = timeutils.utcnow() - self.f(*self.args, **self.kw) - end = timeutils.utcnow() - if not self._running: - break - delay = interval - timeutils.delta_seconds(start, end) - if delay <= 0: - LOG.warn(_('task run outlasted interval by %s sec') % - -delay) - greenthread.sleep(delay if delay > 0 else 0) - except LoopingCallDone, e: - self.stop() - done.send(e.retvalue) - except Exception: - LOG.exception(_('in looping call')) - done.send_exception(*sys.exc_info()) - return - else: - done.send(True) - - self.done = done - - greenthread.spawn_n(_inner) - return self.done - - def stop(self): - self._running = False - - def wait(self): - return self.done.wait() diff --git a/api/glazierapi/openstack/common/notifier/__init__.py b/api/glazierapi/openstack/common/notifier/__init__.py deleted file mode 100644 index 482d54e4..00000000 --- a/api/glazierapi/openstack/common/notifier/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. diff --git a/api/glazierapi/openstack/common/notifier/api.py b/api/glazierapi/openstack/common/notifier/api.py deleted file mode 100644 index 10e5f6cb..00000000 --- a/api/glazierapi/openstack/common/notifier/api.py +++ /dev/null @@ -1,183 +0,0 @@ -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from oslo.config import cfg - -from glazierapi.openstack.common import context -from glazierapi.openstack.common.gettextutils import _ -from glazierapi.openstack.common import importutils -from glazierapi.openstack.common import jsonutils -from glazierapi.openstack.common import log as logging -from glazierapi.openstack.common import timeutils - - -LOG = logging.getLogger(__name__) - -notifier_opts = [ - cfg.MultiStrOpt('notification_driver', - default=[], - deprecated_name='list_notifier_drivers', - help='Driver or drivers to handle sending notifications'), - cfg.StrOpt('default_notification_level', - default='INFO', - help='Default notification level for outgoing notifications'), - cfg.StrOpt('default_publisher_id', - default='$host', - help='Default publisher_id for outgoing notifications'), -] - -CONF = cfg.CONF -CONF.register_opts(notifier_opts) - -WARN = 'WARN' -INFO = 'INFO' -ERROR = 'ERROR' -CRITICAL = 'CRITICAL' -DEBUG = 'DEBUG' - -log_levels = (DEBUG, WARN, INFO, ERROR, CRITICAL) - - -class BadPriorityException(Exception): - pass - - -def notify_decorator(name, fn): - """ decorator for notify which is used from utils.monkey_patch() - - :param name: name of the function - :param function: - object of the function - :returns: function -- decorated function - - """ - def wrapped_func(*args, **kwarg): - body = {} - body['args'] = [] - body['kwarg'] = {} - for arg in args: - body['args'].append(arg) - for key in kwarg: - body['kwarg'][key] = kwarg[key] - - ctxt = context.get_context_from_function_and_args(fn, args, kwarg) - notify(ctxt, - CONF.default_publisher_id, - name, - CONF.default_notification_level, - body) - return fn(*args, **kwarg) - return wrapped_func - - -def publisher_id(service, host=None): - if not host: - host = CONF.host - return "%s.%s" % (service, host) - - -def notify(context, publisher_id, event_type, priority, payload): - """Sends a notification using the specified driver - - :param publisher_id: the source worker_type.host of the message - :param event_type: the literal type of event (ex. Instance Creation) - :param priority: patterned after the enumeration of Python logging - levels in the set (DEBUG, WARN, INFO, ERROR, CRITICAL) - :param payload: A python dictionary of attributes - - Outgoing message format includes the above parameters, and appends the - following: - - message_id - a UUID representing the id for this notification - - timestamp - the GMT timestamp the notification was sent at - - The composite message will be constructed as a dictionary of the above - attributes, which will then be sent via the transport mechanism defined - by the driver. - - Message example:: - - {'message_id': str(uuid.uuid4()), - 'publisher_id': 'compute.host1', - 'timestamp': timeutils.utcnow(), - 'priority': 'WARN', - 'event_type': 'compute.create_instance', - 'payload': {'instance_id': 12, ... }} - - """ - if priority not in log_levels: - raise BadPriorityException( - _('%s not in valid priorities') % priority) - - # Ensure everything is JSON serializable. - payload = jsonutils.to_primitive(payload, convert_instances=True) - - msg = dict(message_id=str(uuid.uuid4()), - publisher_id=publisher_id, - event_type=event_type, - priority=priority, - payload=payload, - timestamp=str(timeutils.utcnow())) - - for driver in _get_drivers(): - try: - driver.notify(context, msg) - except Exception as e: - LOG.exception(_("Problem '%(e)s' attempting to " - "send to notification system. " - "Payload=%(payload)s") - % dict(e=e, payload=payload)) - - -_drivers = None - - -def _get_drivers(): - """Instantiate, cache, and return drivers based on the CONF.""" - global _drivers - if _drivers is None: - _drivers = {} - for notification_driver in CONF.notification_driver: - add_driver(notification_driver) - - return _drivers.values() - - -def add_driver(notification_driver): - """Add a notification driver at runtime.""" - # Make sure the driver list is initialized. - _get_drivers() - if isinstance(notification_driver, basestring): - # Load and add - try: - driver = importutils.import_module(notification_driver) - _drivers[notification_driver] = driver - except ImportError: - LOG.exception(_("Failed to load notifier %s. " - "These notifications will not be sent.") % - notification_driver) - else: - # Driver is already loaded; just add the object. - _drivers[notification_driver] = notification_driver - - -def _reset_drivers(): - """Used by unit tests to reset the drivers.""" - global _drivers - _drivers = None diff --git a/api/glazierapi/openstack/common/notifier/log_notifier.py b/api/glazierapi/openstack/common/notifier/log_notifier.py deleted file mode 100644 index aa571abd..00000000 --- a/api/glazierapi/openstack/common/notifier/log_notifier.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo.config import cfg - -from glazierapi.openstack.common import jsonutils -from glazierapi.openstack.common import log as logging - - -CONF = cfg.CONF - - -def notify(_context, message): - """Notifies the recipient of the desired event given the model. - Log notifications using openstack's default logging system""" - - priority = message.get('priority', - CONF.default_notification_level) - priority = priority.lower() - logger = logging.getLogger( - 'glazierapi.openstack.common.notification.%s' % - message['event_type']) - getattr(logger, priority)(jsonutils.dumps(message)) diff --git a/api/glazierapi/openstack/common/notifier/no_op_notifier.py b/api/glazierapi/openstack/common/notifier/no_op_notifier.py deleted file mode 100644 index ee1ddbdc..00000000 --- a/api/glazierapi/openstack/common/notifier/no_op_notifier.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -def notify(_context, message): - """Notifies the recipient of the desired event given the model""" - pass diff --git a/api/glazierapi/openstack/common/notifier/rabbit_notifier.py b/api/glazierapi/openstack/common/notifier/rabbit_notifier.py deleted file mode 100644 index 3d9c5e4d..00000000 --- a/api/glazierapi/openstack/common/notifier/rabbit_notifier.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -from glazierapi.openstack.common.gettextutils import _ -from glazierapi.openstack.common import log as logging -from glazierapi.openstack.common.notifier import rpc_notifier - -LOG = logging.getLogger(__name__) - - -def notify(context, message): - """Deprecated in Grizzly. Please use rpc_notifier instead.""" - - LOG.deprecated(_("The rabbit_notifier is now deprecated." - " Please use rpc_notifier instead.")) - rpc_notifier.notify(context, message) diff --git a/api/glazierapi/openstack/common/notifier/rpc_notifier.py b/api/glazierapi/openstack/common/notifier/rpc_notifier.py deleted file mode 100644 index 145ac180..00000000 --- a/api/glazierapi/openstack/common/notifier/rpc_notifier.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo.config import cfg - -from glazierapi.openstack.common import context as req_context -from glazierapi.openstack.common.gettextutils import _ -from glazierapi.openstack.common import log as logging -from glazierapi.openstack.common import rpc - -LOG = logging.getLogger(__name__) - -notification_topic_opt = cfg.ListOpt( - 'notification_topics', default=['notifications', ], - help='AMQP topic used for openstack notifications') - -CONF = cfg.CONF -CONF.register_opt(notification_topic_opt) - - -def notify(context, message): - """Sends a notification via RPC""" - if not context: - context = req_context.get_admin_context() - priority = message.get('priority', - CONF.default_notification_level) - priority = priority.lower() - for topic in CONF.notification_topics: - topic = '%s.%s' % (topic, priority) - try: - rpc.notify(context, topic, message) - except Exception: - LOG.exception(_("Could not send notification to %(topic)s. " - "Payload=%(message)s"), locals()) diff --git a/api/glazierapi/openstack/common/notifier/rpc_notifier2.py b/api/glazierapi/openstack/common/notifier/rpc_notifier2.py deleted file mode 100644 index f1e51ca6..00000000 --- a/api/glazierapi/openstack/common/notifier/rpc_notifier2.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -'''messaging based notification driver, with message envelopes''' - -from oslo.config import cfg - -from glazierapi.openstack.common import context as req_context -from glazierapi.openstack.common.gettextutils import _ -from glazierapi.openstack.common import log as logging -from glazierapi.openstack.common import rpc - -LOG = logging.getLogger(__name__) - -notification_topic_opt = cfg.ListOpt( - 'topics', default=['notifications', ], - help='AMQP topic(s) used for openstack notifications') - -opt_group = cfg.OptGroup(name='rpc_notifier2', - title='Options for rpc_notifier2') - -CONF = cfg.CONF -CONF.register_group(opt_group) -CONF.register_opt(notification_topic_opt, opt_group) - - -def notify(context, message): - """Sends a notification via RPC""" - if not context: - context = req_context.get_admin_context() - priority = message.get('priority', - CONF.default_notification_level) - priority = priority.lower() - for topic in CONF.rpc_notifier2.topics: - topic = '%s.%s' % (topic, priority) - try: - rpc.notify(context, topic, message, envelope=True) - except Exception: - LOG.exception(_("Could not send notification to %(topic)s. " - "Payload=%(message)s"), locals()) diff --git a/api/glazierapi/openstack/common/notifier/test_notifier.py b/api/glazierapi/openstack/common/notifier/test_notifier.py deleted file mode 100644 index 5e348803..00000000 --- a/api/glazierapi/openstack/common/notifier/test_notifier.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -NOTIFICATIONS = [] - - -def notify(_context, message): - """Test notifier, stores notifications in memory for unittests.""" - NOTIFICATIONS.append(message) diff --git a/api/glazierapi/openstack/common/service.py b/api/glazierapi/openstack/common/service.py deleted file mode 100644 index 1b89d44e..00000000 --- a/api/glazierapi/openstack/common/service.py +++ /dev/null @@ -1,332 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# Copyright 2011 Justin Santa Barbara -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Generic Node base class for all workers that run on hosts.""" - -import errno -import os -import random -import signal -import sys -import time - -import eventlet -import logging as std_logging -from oslo.config import cfg - -from glazierapi.openstack.common import eventlet_backdoor -from glazierapi.openstack.common.gettextutils import _ -from glazierapi.openstack.common import importutils -from glazierapi.openstack.common import log as logging -from glazierapi.openstack.common import threadgroup - - -rpc = importutils.try_import('glazierapi.openstack.common.rpc') -CONF = cfg.CONF -LOG = logging.getLogger(__name__) - - -class Launcher(object): - """Launch one or more services and wait for them to complete.""" - - def __init__(self): - """Initialize the service launcher. - - :returns: None - - """ - self._services = threadgroup.ThreadGroup() - eventlet_backdoor.initialize_if_enabled() - - @staticmethod - def run_service(service): - """Start and wait for a service to finish. - - :param service: service to run and wait for. - :returns: None - - """ - service.start() - service.wait() - - def launch_service(self, service): - """Load and start the given service. - - :param service: The service you would like to start. - :returns: None - - """ - self._services.add_thread(self.run_service, service) - - def stop(self): - """Stop all services which are currently running. - - :returns: None - - """ - self._services.stop() - - def wait(self): - """Waits until all services have been stopped, and then returns. - - :returns: None - - """ - self._services.wait() - - -class SignalExit(SystemExit): - def __init__(self, signo, exccode=1): - super(SignalExit, self).__init__(exccode) - self.signo = signo - - -class ServiceLauncher(Launcher): - def _handle_signal(self, signo, frame): - # Allow the process to be killed again and die from natural causes - signal.signal(signal.SIGTERM, signal.SIG_DFL) - signal.signal(signal.SIGINT, signal.SIG_DFL) - - raise SignalExit(signo) - - def wait(self): - signal.signal(signal.SIGTERM, self._handle_signal) - signal.signal(signal.SIGINT, self._handle_signal) - - LOG.debug(_('Full set of CONF:')) - CONF.log_opt_values(LOG, std_logging.DEBUG) - - status = None - try: - super(ServiceLauncher, self).wait() - except SignalExit as exc: - signame = {signal.SIGTERM: 'SIGTERM', - signal.SIGINT: 'SIGINT'}[exc.signo] - LOG.info(_('Caught %s, exiting'), signame) - status = exc.code - except SystemExit as exc: - status = exc.code - finally: - if rpc: - rpc.cleanup() - self.stop() - return status - - -class ServiceWrapper(object): - def __init__(self, service, workers): - self.service = service - self.workers = workers - self.children = set() - self.forktimes = [] - - -class ProcessLauncher(object): - def __init__(self): - self.children = {} - self.sigcaught = None - self.running = True - rfd, self.writepipe = os.pipe() - self.readpipe = eventlet.greenio.GreenPipe(rfd, 'r') - - signal.signal(signal.SIGTERM, self._handle_signal) - signal.signal(signal.SIGINT, self._handle_signal) - - def _handle_signal(self, signo, frame): - self.sigcaught = signo - self.running = False - - # Allow the process to be killed again and die from natural causes - signal.signal(signal.SIGTERM, signal.SIG_DFL) - signal.signal(signal.SIGINT, signal.SIG_DFL) - - def _pipe_watcher(self): - # This will block until the write end is closed when the parent - # dies unexpectedly - self.readpipe.read() - - LOG.info(_('Parent process has died unexpectedly, exiting')) - - sys.exit(1) - - def _child_process(self, service): - # Setup child signal handlers differently - def _sigterm(*args): - signal.signal(signal.SIGTERM, signal.SIG_DFL) - raise SignalExit(signal.SIGTERM) - - signal.signal(signal.SIGTERM, _sigterm) - # Block SIGINT and let the parent send us a SIGTERM - signal.signal(signal.SIGINT, signal.SIG_IGN) - - # Reopen the eventlet hub to make sure we don't share an epoll - # fd with parent and/or siblings, which would be bad - eventlet.hubs.use_hub() - - # Close write to ensure only parent has it open - os.close(self.writepipe) - # Create greenthread to watch for parent to close pipe - eventlet.spawn_n(self._pipe_watcher) - - # Reseed random number generator - random.seed() - - launcher = Launcher() - launcher.run_service(service) - - def _start_child(self, wrap): - if len(wrap.forktimes) > wrap.workers: - # Limit ourselves to one process a second (over the period of - # number of workers * 1 second). This will allow workers to - # start up quickly but ensure we don't fork off children that - # die instantly too quickly. - if time.time() - wrap.forktimes[0] < wrap.workers: - LOG.info(_('Forking too fast, sleeping')) - time.sleep(1) - - wrap.forktimes.pop(0) - - wrap.forktimes.append(time.time()) - - pid = os.fork() - if pid == 0: - # NOTE(johannes): All exceptions are caught to ensure this - # doesn't fallback into the loop spawning children. It would - # be bad for a child to spawn more children. - status = 0 - try: - self._child_process(wrap.service) - except SignalExit as exc: - signame = {signal.SIGTERM: 'SIGTERM', - signal.SIGINT: 'SIGINT'}[exc.signo] - LOG.info(_('Caught %s, exiting'), signame) - status = exc.code - except SystemExit as exc: - status = exc.code - except BaseException: - LOG.exception(_('Unhandled exception')) - status = 2 - finally: - wrap.service.stop() - - os._exit(status) - - LOG.info(_('Started child %d'), pid) - - wrap.children.add(pid) - self.children[pid] = wrap - - return pid - - def launch_service(self, service, workers=1): - wrap = ServiceWrapper(service, workers) - - LOG.info(_('Starting %d workers'), wrap.workers) - while self.running and len(wrap.children) < wrap.workers: - self._start_child(wrap) - - def _wait_child(self): - try: - # Don't block if no child processes have exited - pid, status = os.waitpid(0, os.WNOHANG) - if not pid: - return None - except OSError as exc: - if exc.errno not in (errno.EINTR, errno.ECHILD): - raise - return None - - if os.WIFSIGNALED(status): - sig = os.WTERMSIG(status) - LOG.info(_('Child %(pid)d killed by signal %(sig)d'), - dict(pid=pid, sig=sig)) - else: - code = os.WEXITSTATUS(status) - LOG.info(_('Child %(pid)s exited with status %(code)d'), - dict(pid=pid, code=code)) - - if pid not in self.children: - LOG.warning(_('pid %d not in child list'), pid) - return None - - wrap = self.children.pop(pid) - wrap.children.remove(pid) - return wrap - - def wait(self): - """Loop waiting on children to die and respawning as necessary""" - - LOG.debug(_('Full set of CONF:')) - CONF.log_opt_values(LOG, std_logging.DEBUG) - - while self.running: - wrap = self._wait_child() - if not wrap: - # Yield to other threads if no children have exited - # Sleep for a short time to avoid excessive CPU usage - # (see bug #1095346) - eventlet.greenthread.sleep(.01) - continue - - while self.running and len(wrap.children) < wrap.workers: - self._start_child(wrap) - - if self.sigcaught: - signame = {signal.SIGTERM: 'SIGTERM', - signal.SIGINT: 'SIGINT'}[self.sigcaught] - LOG.info(_('Caught %s, stopping children'), signame) - - for pid in self.children: - try: - os.kill(pid, signal.SIGTERM) - except OSError as exc: - if exc.errno != errno.ESRCH: - raise - - # Wait for children to die - if self.children: - LOG.info(_('Waiting on %d children to exit'), len(self.children)) - while self.children: - self._wait_child() - - -class Service(object): - """Service object for binaries running on hosts.""" - - def __init__(self, threads=1000): - self.tg = threadgroup.ThreadGroup(threads) - - def start(self): - pass - - def stop(self): - self.tg.stop() - - def wait(self): - self.tg.wait() - - -def launch(service, workers=None): - if workers: - launcher = ProcessLauncher() - launcher.launch_service(service, workers=workers) - else: - launcher = ServiceLauncher() - launcher.launch_service(service) - return launcher diff --git a/api/glazierapi/openstack/common/setup.py b/api/glazierapi/openstack/common/setup.py deleted file mode 100644 index 80a0ecee..00000000 --- a/api/glazierapi/openstack/common/setup.py +++ /dev/null @@ -1,359 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack LLC. -# Copyright 2012-2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Utilities with minimum-depends for use in setup.py -""" - -import email -import os -import re -import subprocess -import sys - -from setuptools.command import sdist - - -def parse_mailmap(mailmap='.mailmap'): - mapping = {} - if os.path.exists(mailmap): - with open(mailmap, 'r') as fp: - for l in fp: - try: - canonical_email, alias = re.match( - r'[^#]*?(<.+>).*(<.+>).*', l).groups() - except AttributeError: - continue - mapping[alias] = canonical_email - return mapping - - -def _parse_git_mailmap(git_dir, mailmap='.mailmap'): - mailmap = os.path.join(os.path.dirname(git_dir), mailmap) - return parse_mailmap(mailmap) - - -def canonicalize_emails(changelog, mapping): - """Takes in a string and an email alias mapping and replaces all - instances of the aliases in the string with their real email. - """ - for alias, email_address in mapping.iteritems(): - changelog = changelog.replace(alias, email_address) - return changelog - - -# Get requirements from the first file that exists -def get_reqs_from_files(requirements_files): - for requirements_file in requirements_files: - if os.path.exists(requirements_file): - with open(requirements_file, 'r') as fil: - return fil.read().split('\n') - return [] - - -def parse_requirements(requirements_files=['requirements.txt', - 'tools/pip-requires']): - requirements = [] - for line in get_reqs_from_files(requirements_files): - # For the requirements list, we need to inject only the portion - # after egg= so that distutils knows the package it's looking for - # such as: - # -e git://github.com/openstack/nova/master#egg=nova - if re.match(r'\s*-e\s+', line): - requirements.append(re.sub(r'\s*-e\s+.*#egg=(.*)$', r'\1', - line)) - # such as: - # http://github.com/openstack/nova/zipball/master#egg=nova - elif re.match(r'\s*https?:', line): - requirements.append(re.sub(r'\s*https?:.*#egg=(.*)$', r'\1', - line)) - # -f lines are for index locations, and don't get used here - elif re.match(r'\s*-f\s+', line): - pass - # argparse is part of the standard library starting with 2.7 - # adding it to the requirements list screws distro installs - elif line == 'argparse' and sys.version_info >= (2, 7): - pass - else: - requirements.append(line) - - return requirements - - -def parse_dependency_links(requirements_files=['requirements.txt', - 'tools/pip-requires']): - dependency_links = [] - # dependency_links inject alternate locations to find packages listed - # in requirements - for line in get_reqs_from_files(requirements_files): - # skip comments and blank lines - if re.match(r'(\s*#)|(\s*$)', line): - continue - # lines with -e or -f need the whole line, minus the flag - if re.match(r'\s*-[ef]\s+', line): - dependency_links.append(re.sub(r'\s*-[ef]\s+', '', line)) - # lines that are only urls can go in unmolested - elif re.match(r'\s*https?:', line): - dependency_links.append(line) - return dependency_links - - -def _run_shell_command(cmd, throw_on_error=False): - if os.name == 'nt': - output = subprocess.Popen(["cmd.exe", "/C", cmd], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - else: - output = subprocess.Popen(["/bin/sh", "-c", cmd], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - out = output.communicate() - if output.returncode and throw_on_error: - raise Exception("%s returned %d" % cmd, output.returncode) - if len(out) == 0: - return None - if len(out[0].strip()) == 0: - return None - return out[0].strip() - - -def _get_git_directory(): - parent_dir = os.path.dirname(__file__) - while True: - git_dir = os.path.join(parent_dir, '.git') - if os.path.exists(git_dir): - return git_dir - parent_dir, child = os.path.split(parent_dir) - if not child: # reached to root dir - return None - - -def write_git_changelog(): - """Write a changelog based on the git changelog.""" - new_changelog = 'ChangeLog' - git_dir = _get_git_directory() - if not os.getenv('SKIP_WRITE_GIT_CHANGELOG'): - if git_dir: - git_log_cmd = 'git --git-dir=%s log --stat' % git_dir - changelog = _run_shell_command(git_log_cmd) - mailmap = _parse_git_mailmap(git_dir) - with open(new_changelog, "w") as changelog_file: - changelog_file.write(canonicalize_emails(changelog, mailmap)) - else: - open(new_changelog, 'w').close() - - -def generate_authors(): - """Create AUTHORS file using git commits.""" - jenkins_email = 'jenkins@review.(openstack|stackforge).org' - old_authors = 'AUTHORS.in' - new_authors = 'AUTHORS' - git_dir = _get_git_directory() - if not os.getenv('SKIP_GENERATE_AUTHORS'): - if git_dir: - # don't include jenkins email address in AUTHORS file - git_log_cmd = ("git --git-dir=" + git_dir + - " log --format='%aN <%aE>' | sort -u | " - "egrep -v '" + jenkins_email + "'") - changelog = _run_shell_command(git_log_cmd) - mailmap = _parse_git_mailmap(git_dir) - with open(new_authors, 'w') as new_authors_fh: - new_authors_fh.write(canonicalize_emails(changelog, mailmap)) - if os.path.exists(old_authors): - with open(old_authors, "r") as old_authors_fh: - new_authors_fh.write('\n' + old_authors_fh.read()) - else: - open(new_authors, 'w').close() - - -_rst_template = """%(heading)s -%(underline)s - -.. automodule:: %(module)s - :members: - :undoc-members: - :show-inheritance: -""" - - -def get_cmdclass(): - """Return dict of commands to run from setup.py.""" - - cmdclass = dict() - - def _find_modules(arg, dirname, files): - for filename in files: - if filename.endswith('.py') and filename != '__init__.py': - arg["%s.%s" % (dirname.replace('/', '.'), - filename[:-3])] = True - - class LocalSDist(sdist.sdist): - """Builds the ChangeLog and Authors files from VC first.""" - - def run(self): - write_git_changelog() - generate_authors() - # sdist.sdist is an old style class, can't use super() - sdist.sdist.run(self) - - cmdclass['sdist'] = LocalSDist - - # If Sphinx is installed on the box running setup.py, - # enable setup.py to build the documentation, otherwise, - # just ignore it - try: - from sphinx.setup_command import BuildDoc - - class LocalBuildDoc(BuildDoc): - - builders = ['html', 'man'] - - def generate_autoindex(self): - print "**Autodocumenting from %s" % os.path.abspath(os.curdir) - modules = {} - option_dict = self.distribution.get_option_dict('build_sphinx') - source_dir = os.path.join(option_dict['source_dir'][1], 'api') - if not os.path.exists(source_dir): - os.makedirs(source_dir) - for pkg in self.distribution.packages: - if '.' not in pkg: - os.path.walk(pkg, _find_modules, modules) - module_list = modules.keys() - module_list.sort() - autoindex_filename = os.path.join(source_dir, 'autoindex.rst') - with open(autoindex_filename, 'w') as autoindex: - autoindex.write(""".. toctree:: - :maxdepth: 1 - -""") - for module in module_list: - output_filename = os.path.join(source_dir, - "%s.rst" % module) - heading = "The :mod:`%s` Module" % module - underline = "=" * len(heading) - values = dict(module=module, heading=heading, - underline=underline) - - print "Generating %s" % output_filename - with open(output_filename, 'w') as output_file: - output_file.write(_rst_template % values) - autoindex.write(" %s.rst\n" % module) - - def run(self): - if not os.getenv('SPHINX_DEBUG'): - self.generate_autoindex() - - for builder in self.builders: - self.builder = builder - self.finalize_options() - self.project = self.distribution.get_name() - self.version = self.distribution.get_version() - self.release = self.distribution.get_version() - BuildDoc.run(self) - - class LocalBuildLatex(LocalBuildDoc): - builders = ['latex'] - - cmdclass['build_sphinx'] = LocalBuildDoc - cmdclass['build_sphinx_latex'] = LocalBuildLatex - except ImportError: - pass - - return cmdclass - - -def _get_revno(git_dir): - """Return the number of commits since the most recent tag. - - We use git-describe to find this out, but if there are no - tags then we fall back to counting commits since the beginning - of time. - """ - describe = _run_shell_command( - "git --git-dir=%s describe --always" % git_dir) - if "-" in describe: - return describe.rsplit("-", 2)[-2] - - # no tags found - revlist = _run_shell_command( - "git --git-dir=%s rev-list --abbrev-commit HEAD" % git_dir) - return len(revlist.splitlines()) - - -def _get_version_from_git(pre_version): - """Return a version which is equal to the tag that's on the current - revision if there is one, or tag plus number of additional revisions - if the current revision has no tag.""" - - git_dir = _get_git_directory() - if git_dir: - if pre_version: - try: - return _run_shell_command( - "git --git-dir=" + git_dir + " describe --exact-match", - throw_on_error=True).replace('-', '.') - except Exception: - sha = _run_shell_command( - "git --git-dir=" + git_dir + " log -n1 --pretty=format:%h") - return "%s.a%s.g%s" % (pre_version, _get_revno(git_dir), sha) - else: - return _run_shell_command( - "git --git-dir=" + git_dir + " describe --always").replace( - '-', '.') - return None - - -def _get_version_from_pkg_info(package_name): - """Get the version from PKG-INFO file if we can.""" - try: - pkg_info_file = open('PKG-INFO', 'r') - except (IOError, OSError): - return None - try: - pkg_info = email.message_from_file(pkg_info_file) - except email.MessageError: - return None - # Check to make sure we're in our own dir - if pkg_info.get('Name', None) != package_name: - return None - return pkg_info.get('Version', None) - - -def get_version(package_name, pre_version=None): - """Get the version of the project. First, try getting it from PKG-INFO, if - it exists. If it does, that means we're in a distribution tarball or that - install has happened. Otherwise, if there is no PKG-INFO file, pull the - version from git. - - We do not support setup.py version sanity in git archive tarballs, nor do - we support packagers directly sucking our git repo into theirs. We expect - that a source tarball be made from our git repo - or that if someone wants - to make a source tarball from a fork of our repo with additional tags in it - that they understand and desire the results of doing that. - """ - version = os.environ.get("OSLO_PACKAGE_VERSION", None) - if version: - return version - version = _get_version_from_pkg_info(package_name) - if version: - return version - version = _get_version_from_git(pre_version) - if version: - return version - raise Exception("Versioning for this project requires either an sdist" - " tarball, or access to an upstream git repository.") diff --git a/api/glazierapi/openstack/common/sslutils.py b/api/glazierapi/openstack/common/sslutils.py deleted file mode 100644 index 998f4fdb..00000000 --- a/api/glazierapi/openstack/common/sslutils.py +++ /dev/null @@ -1,80 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2013 IBM -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os -import ssl - -from oslo.config import cfg - -from glazierapi.openstack.common.gettextutils import _ - - -ssl_opts = [ - cfg.StrOpt('ca_file', - default=None, - help="CA certificate file to use to verify " - "connecting clients"), - cfg.StrOpt('cert_file', - default=None, - help="Certificate file to use when starting " - "the server securely"), - cfg.StrOpt('key_file', - default=None, - help="Private key file to use when starting " - "the server securely"), -] - - -CONF = cfg.CONF -CONF.register_opts(ssl_opts, "ssl") - - -def is_enabled(): - cert_file = CONF.ssl.cert_file - key_file = CONF.ssl.key_file - ca_file = CONF.ssl.ca_file - use_ssl = cert_file or key_file - - if cert_file and not os.path.exists(cert_file): - raise RuntimeError(_("Unable to find cert_file : %s") % cert_file) - - if ca_file and not os.path.exists(ca_file): - raise RuntimeError(_("Unable to find ca_file : %s") % ca_file) - - if key_file and not os.path.exists(key_file): - raise RuntimeError(_("Unable to find key_file : %s") % key_file) - - if use_ssl and (not cert_file or not key_file): - raise RuntimeError(_("When running server in SSL mode, you must " - "specify both a cert_file and key_file " - "option value in your configuration file")) - - return use_ssl - - -def wrap(sock): - ssl_kwargs = { - 'server_side': True, - 'certfile': CONF.ssl.cert_file, - 'keyfile': CONF.ssl.key_file, - 'cert_reqs': ssl.CERT_NONE, - } - - if CONF.ssl.ca_file: - ssl_kwargs['ca_certs'] = CONF.ssl.ca_file - ssl_kwargs['cert_reqs'] = ssl.CERT_REQUIRED - - return ssl.wrap_socket(sock, **ssl_kwargs) diff --git a/api/glazierapi/openstack/common/threadgroup.py b/api/glazierapi/openstack/common/threadgroup.py deleted file mode 100644 index f38e7464..00000000 --- a/api/glazierapi/openstack/common/threadgroup.py +++ /dev/null @@ -1,114 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from eventlet import greenlet -from eventlet import greenpool -from eventlet import greenthread - -from glazierapi.openstack.common import log as logging -from glazierapi.openstack.common import loopingcall - - -LOG = logging.getLogger(__name__) - - -def _thread_done(gt, *args, **kwargs): - """ Callback function to be passed to GreenThread.link() when we spawn() - Calls the :class:`ThreadGroup` to notify if. - - """ - kwargs['group'].thread_done(kwargs['thread']) - - -class Thread(object): - """ Wrapper around a greenthread, that holds a reference to the - :class:`ThreadGroup`. The Thread will notify the :class:`ThreadGroup` when - it has done so it can be removed from the threads list. - """ - def __init__(self, thread, group): - self.thread = thread - self.thread.link(_thread_done, group=group, thread=self) - - def stop(self): - self.thread.kill() - - def wait(self): - return self.thread.wait() - - -class ThreadGroup(object): - """ The point of the ThreadGroup classis to: - - * keep track of timers and greenthreads (making it easier to stop them - when need be). - * provide an easy API to add timers. - """ - def __init__(self, thread_pool_size=10): - self.pool = greenpool.GreenPool(thread_pool_size) - self.threads = [] - self.timers = [] - - def add_timer(self, interval, callback, initial_delay=None, - *args, **kwargs): - pulse = loopingcall.LoopingCall(callback, *args, **kwargs) - pulse.start(interval=interval, - initial_delay=initial_delay) - self.timers.append(pulse) - - def add_thread(self, callback, *args, **kwargs): - gt = self.pool.spawn(callback, *args, **kwargs) - th = Thread(gt, self) - self.threads.append(th) - - def thread_done(self, thread): - self.threads.remove(thread) - - def stop(self): - current = greenthread.getcurrent() - for x in self.threads: - if x is current: - # don't kill the current thread. - continue - try: - x.stop() - except Exception as ex: - LOG.exception(ex) - - for x in self.timers: - try: - x.stop() - except Exception as ex: - LOG.exception(ex) - self.timers = [] - - def wait(self): - for x in self.timers: - try: - x.wait() - except greenlet.GreenletExit: - pass - except Exception as ex: - LOG.exception(ex) - current = greenthread.getcurrent() - for x in self.threads: - if x is current: - continue - try: - x.wait() - except greenlet.GreenletExit: - pass - except Exception as ex: - LOG.exception(ex) diff --git a/api/glazierapi/openstack/common/timeutils.py b/api/glazierapi/openstack/common/timeutils.py deleted file mode 100644 index e2c27405..00000000 --- a/api/glazierapi/openstack/common/timeutils.py +++ /dev/null @@ -1,182 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Time related utilities and helper functions. -""" - -import calendar -import datetime - -import iso8601 - - -TIME_FORMAT = "%Y-%m-%dT%H:%M:%S" -PERFECT_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%f" - - -def isotime(at=None): - """Stringify time in ISO 8601 format""" - if not at: - at = utcnow() - str = at.strftime(TIME_FORMAT) - tz = at.tzinfo.tzname(None) if at.tzinfo else 'UTC' - str += ('Z' if tz == 'UTC' else tz) - return str - - -def parse_isotime(timestr): - """Parse time from ISO 8601 format""" - try: - return iso8601.parse_date(timestr) - except iso8601.ParseError as e: - raise ValueError(e.message) - except TypeError as e: - raise ValueError(e.message) - - -def strtime(at=None, fmt=PERFECT_TIME_FORMAT): - """Returns formatted utcnow.""" - if not at: - at = utcnow() - return at.strftime(fmt) - - -def parse_strtime(timestr, fmt=PERFECT_TIME_FORMAT): - """Turn a formatted time back into a datetime.""" - return datetime.datetime.strptime(timestr, fmt) - - -def normalize_time(timestamp): - """Normalize time in arbitrary timezone to UTC naive object""" - offset = timestamp.utcoffset() - if offset is None: - return timestamp - return timestamp.replace(tzinfo=None) - offset - - -def is_older_than(before, seconds): - """Return True if before is older than seconds.""" - if isinstance(before, basestring): - before = parse_strtime(before).replace(tzinfo=None) - return utcnow() - before > datetime.timedelta(seconds=seconds) - - -def is_newer_than(after, seconds): - """Return True if after is newer than seconds.""" - if isinstance(after, basestring): - after = parse_strtime(after).replace(tzinfo=None) - return after - utcnow() > datetime.timedelta(seconds=seconds) - - -def utcnow_ts(): - """Timestamp version of our utcnow function.""" - return calendar.timegm(utcnow().timetuple()) - - -def utcnow(): - """Overridable version of utils.utcnow.""" - if utcnow.override_time: - try: - return utcnow.override_time.pop(0) - except AttributeError: - return utcnow.override_time - return datetime.datetime.utcnow() - - -def iso8601_from_timestamp(timestamp): - """Returns a iso8601 formated date from timestamp""" - return isotime(datetime.datetime.utcfromtimestamp(timestamp)) - - -utcnow.override_time = None - - -def set_time_override(override_time=datetime.datetime.utcnow()): - """ - Override utils.utcnow to return a constant time or a list thereof, - one at a time. - """ - utcnow.override_time = override_time - - -def advance_time_delta(timedelta): - """Advance overridden time using a datetime.timedelta.""" - assert(not utcnow.override_time is None) - try: - for dt in utcnow.override_time: - dt += timedelta - except TypeError: - utcnow.override_time += timedelta - - -def advance_time_seconds(seconds): - """Advance overridden time by seconds.""" - advance_time_delta(datetime.timedelta(0, seconds)) - - -def clear_time_override(): - """Remove the overridden time.""" - utcnow.override_time = None - - -def marshall_now(now=None): - """Make an rpc-safe datetime with microseconds. - - Note: tzinfo is stripped, but not required for relative times.""" - if not now: - now = utcnow() - return dict(day=now.day, month=now.month, year=now.year, hour=now.hour, - minute=now.minute, second=now.second, - microsecond=now.microsecond) - - -def unmarshall_time(tyme): - """Unmarshall a datetime dict.""" - return datetime.datetime(day=tyme['day'], - month=tyme['month'], - year=tyme['year'], - hour=tyme['hour'], - minute=tyme['minute'], - second=tyme['second'], - microsecond=tyme['microsecond']) - - -def delta_seconds(before, after): - """ - Compute the difference in seconds between two date, time, or - datetime objects (as a float, to microsecond resolution). - """ - delta = after - before - try: - return delta.total_seconds() - except AttributeError: - return ((delta.days * 24 * 3600) + delta.seconds + - float(delta.microseconds) / (10 ** 6)) - - -def is_soon(dt, window): - """ - Determines if time is going to happen in the next window seconds. - - :params dt: the time - :params window: minimum seconds to remain to consider the time not soon - - :return: True if expiration is within the given duration - """ - soon = (utcnow() + datetime.timedelta(seconds=window)) - return normalize_time(dt) <= soon diff --git a/api/glazierapi/openstack/common/uuidutils.py b/api/glazierapi/openstack/common/uuidutils.py deleted file mode 100644 index 7608acb9..00000000 --- a/api/glazierapi/openstack/common/uuidutils.py +++ /dev/null @@ -1,39 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright (c) 2012 Intel Corporation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -UUID related utilities and helper functions. -""" - -import uuid - - -def generate_uuid(): - return str(uuid.uuid4()) - - -def is_uuid_like(val): - """Returns validation of a value as a UUID. - - For our purposes, a UUID is a canonical form string: - aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa - - """ - try: - return str(uuid.UUID(val)) == val - except (TypeError, ValueError, AttributeError): - return False diff --git a/api/glazierapi/openstack/common/version.py b/api/glazierapi/openstack/common/version.py deleted file mode 100644 index e4eb6530..00000000 --- a/api/glazierapi/openstack/common/version.py +++ /dev/null @@ -1,94 +0,0 @@ - -# Copyright 2012 OpenStack LLC -# Copyright 2012-2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Utilities for consuming the version from pkg_resources. -""" - -import pkg_resources - - -class VersionInfo(object): - - def __init__(self, package): - """Object that understands versioning for a package - :param package: name of the python package, such as glance, or - python-glanceclient - """ - self.package = package - self.release = None - self.version = None - self._cached_version = None - - def __str__(self): - """Make the VersionInfo object behave like a string.""" - return self.version_string() - - def __repr__(self): - """Include the name.""" - return "VersionInfo(%s:%s)" % (self.package, self.version_string()) - - def _get_version_from_pkg_resources(self): - """Get the version of the package from the pkg_resources record - associated with the package.""" - try: - requirement = pkg_resources.Requirement.parse(self.package) - provider = pkg_resources.get_provider(requirement) - return provider.version - except pkg_resources.DistributionNotFound: - # The most likely cause for this is running tests in a tree - # produced from a tarball where the package itself has not been - # installed into anything. Revert to setup-time logic. - from glazierapi.openstack.common import setup - return setup.get_version(self.package) - - def release_string(self): - """Return the full version of the package including suffixes indicating - VCS status. - """ - if self.release is None: - self.release = self._get_version_from_pkg_resources() - - return self.release - - def version_string(self): - """Return the short version minus any alpha/beta tags.""" - if self.version is None: - parts = [] - for part in self.release_string().split('.'): - if part[0].isdigit(): - parts.append(part) - else: - break - self.version = ".".join(parts) - - return self.version - - # Compatibility functions - canonical_version_string = version_string - version_string_with_vcs = release_string - - def cached_version_string(self, prefix=""): - """Generate an object which will expand in a string context to - the results of version_string(). We do this so that don't - call into pkg_resources every time we start up a program when - passing version information into the CONF constructor, but - rather only do the calculation when and if a version is requested - """ - if not self._cached_version: - self._cached_version = "%s%s" % (prefix, - self.version_string()) - return self._cached_version diff --git a/api/glazierapi/openstack/common/wsgi.py b/api/glazierapi/openstack/common/wsgi.py deleted file mode 100644 index e4f15fc0..00000000 --- a/api/glazierapi/openstack/common/wsgi.py +++ /dev/null @@ -1,797 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Utility methods for working with WSGI servers.""" - -import eventlet -eventlet.patcher.monkey_patch(all=False, socket=True) - -import datetime -import errno -import socket -import sys -import time - -import eventlet.wsgi -from oslo.config import cfg -import routes -import routes.middleware -import webob.dec -import webob.exc -from xml.dom import minidom -from xml.parsers import expat - -from glazierapi.openstack.common import exception -from glazierapi.openstack.common.gettextutils import _ -from glazierapi.openstack.common import jsonutils -from glazierapi.openstack.common import log as logging -from glazierapi.openstack.common import service -from glazierapi.openstack.common import sslutils -from glazierapi.openstack.common import xmlutils - -socket_opts = [ - cfg.IntOpt('backlog', - default=4096, - help="Number of backlog requests to configure the socket with"), - cfg.IntOpt('tcp_keepidle', - default=600, - help="Sets the value of TCP_KEEPIDLE in seconds for each " - "server socket. Not supported on OS X."), -] - -CONF = cfg.CONF -CONF.register_opts(socket_opts) - -LOG = logging.getLogger(__name__) - - -def run_server(application, port): - """Run a WSGI server with the given application.""" - sock = eventlet.listen(('0.0.0.0', port)) - eventlet.wsgi.server(sock, application) - - -class Service(service.Service): - """ - Provides a Service API for wsgi servers. - - This gives us the ability to launch wsgi servers with the - Launcher classes in service.py. - """ - - def __init__(self, application, port, - host='0.0.0.0', backlog=4096, threads=1000): - self.application = application - self._port = port - self._host = host - self._backlog = backlog if backlog else CONF.backlog - super(Service, self).__init__(threads) - - def _get_socket(self, host, port, backlog): - # TODO(dims): eventlet's green dns/socket module does not actually - # support IPv6 in getaddrinfo(). We need to get around this in the - # future or monitor upstream for a fix - info = socket.getaddrinfo(host, - port, - socket.AF_UNSPEC, - socket.SOCK_STREAM)[0] - family = info[0] - bind_addr = info[-1] - - sock = None - retry_until = time.time() + 30 - while not sock and time.time() < retry_until: - try: - sock = eventlet.listen(bind_addr, - backlog=backlog, - family=family) - if sslutils.is_enabled(): - sock = sslutils.wrap(sock) - - except socket.error, err: - if err.args[0] != errno.EADDRINUSE: - raise - eventlet.sleep(0.1) - if not sock: - raise RuntimeError(_("Could not bind to %(host)s:%(port)s " - "after trying for 30 seconds") % - {'host': host, 'port': port}) - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - # sockets can hang around forever without keepalive - sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) - - # This option isn't available in the OS X version of eventlet - if hasattr(socket, 'TCP_KEEPIDLE'): - sock.setsockopt(socket.IPPROTO_TCP, - socket.TCP_KEEPIDLE, - CONF.tcp_keepidle) - - return sock - - def start(self): - """Start serving this service using the provided server instance. - - :returns: None - - """ - super(Service, self).start() - self._socket = self._get_socket(self._host, self._port, self._backlog) - self.tg.add_thread(self._run, self.application, self._socket) - - @property - def backlog(self): - return self._backlog - - @property - def host(self): - return self._socket.getsockname()[0] if self._socket else self._host - - @property - def port(self): - return self._socket.getsockname()[1] if self._socket else self._port - - def stop(self): - """Stop serving this API. - - :returns: None - - """ - super(Service, self).stop() - - def _run(self, application, socket): - """Start a WSGI server in a new green thread.""" - logger = logging.getLogger('eventlet.wsgi') - eventlet.wsgi.server(socket, - application, - custom_pool=self.tg.pool, - log=logging.WritableLogger(logger)) - - -class Middleware(object): - """ - Base WSGI middleware wrapper. These classes require an application to be - initialized that will be called next. By default the middleware will - simply call its wrapped app, or you can override __call__ to customize its - behavior. - """ - - def __init__(self, application): - self.application = application - - def process_request(self, req): - """ - Called on each request. - - If this returns None, the next application down the stack will be - executed. If it returns a response then that response will be returned - and execution will stop here. - """ - return None - - def process_response(self, response): - """Do whatever you'd like to the response.""" - return response - - @webob.dec.wsgify - def __call__(self, req): - response = self.process_request(req) - if response: - return response - response = req.get_response(self.application) - return self.process_response(response) - - -class Debug(Middleware): - """ - Helper class that can be inserted into any WSGI application chain - to get information about the request and response. - """ - - @webob.dec.wsgify - def __call__(self, req): - print ("*" * 40) + " REQUEST ENVIRON" - for key, value in req.environ.items(): - print key, "=", value - print - resp = req.get_response(self.application) - - print ("*" * 40) + " RESPONSE HEADERS" - for (key, value) in resp.headers.iteritems(): - print key, "=", value - print - - resp.app_iter = self.print_generator(resp.app_iter) - - return resp - - @staticmethod - def print_generator(app_iter): - """ - Iterator that prints the contents of a wrapper string iterator - when iterated. - """ - print ("*" * 40) + " BODY" - for part in app_iter: - sys.stdout.write(part) - sys.stdout.flush() - yield part - print - - -class Router(object): - - """ - WSGI middleware that maps incoming requests to WSGI apps. - """ - - def __init__(self, mapper): - """ - Create a router for the given routes.Mapper. - - Each route in `mapper` must specify a 'controller', which is a - WSGI app to call. You'll probably want to specify an 'action' as - well and have your controller be a wsgi.Controller, who will route - the request to the action method. - - Examples: - mapper = routes.Mapper() - sc = ServerController() - - # Explicit mapping of one route to a controller+action - mapper.connect(None, "/svrlist", controller=sc, action="list") - - # Actions are all implicitly defined - mapper.resource("server", "servers", controller=sc) - - # Pointing to an arbitrary WSGI app. You can specify the - # {path_info:.*} parameter so the target app can be handed just that - # section of the URL. - mapper.connect(None, "/v1.0/{path_info:.*}", controller=BlogApp()) - """ - self.map = mapper - self._router = routes.middleware.RoutesMiddleware(self._dispatch, - self.map) - - @webob.dec.wsgify - def __call__(self, req): - """ - Route the incoming request to a controller based on self.map. - If no match, return a 404. - """ - return self._router - - @staticmethod - @webob.dec.wsgify - def _dispatch(req): - """ - Called by self._router after matching the incoming request to a route - and putting the information into req.environ. Either returns 404 - or the routed WSGI app's response. - """ - match = req.environ['wsgiorg.routing_args'][1] - if not match: - return webob.exc.HTTPNotFound() - app = match['controller'] - return app - - -class Request(webob.Request): - """Add some Openstack API-specific logic to the base webob.Request.""" - - default_request_content_types = ('application/json', 'application/xml') - default_accept_types = ('application/json', 'application/xml') - default_accept_type = 'application/json' - - def best_match_content_type(self, supported_content_types=None): - """Determine the requested response content-type. - - Based on the query extension then the Accept header. - Defaults to default_accept_type if we don't find a preference - - """ - supported_content_types = (supported_content_types or - self.default_accept_types) - - parts = self.path.rsplit('.', 1) - if len(parts) > 1: - ctype = 'application/{0}'.format(parts[1]) - if ctype in supported_content_types: - return ctype - - bm = self.accept.best_match(supported_content_types) - return bm or self.default_accept_type - - def get_content_type(self, allowed_content_types=None): - """Determine content type of the request body. - - Does not do any body introspection, only checks header - - """ - if "Content-Type" not in self.headers: - return None - - content_type = self.content_type - allowed_content_types = (allowed_content_types or - self.default_request_content_types) - - if content_type not in allowed_content_types: - raise exception.InvalidContentType(content_type=content_type) - return content_type - - -class Resource(object): - """ - WSGI app that handles (de)serialization and controller dispatch. - - Reads routing information supplied by RoutesMiddleware and calls - the requested action method upon its deserializer, controller, - and serializer. Those three objects may implement any of the basic - controller action methods (create, update, show, index, delete) - along with any that may be specified in the api router. A 'default' - method may also be implemented to be used in place of any - non-implemented actions. Deserializer methods must accept a request - argument and return a dictionary. Controller methods must accept a - request argument. Additionally, they must also accept keyword - arguments that represent the keys returned by the Deserializer. They - may raise a webob.exc exception or return a dict, which will be - serialized by requested content type. - """ - def __init__(self, controller, deserializer=None, serializer=None): - """ - :param controller: object that implement methods created by routes lib - :param deserializer: object that supports webob request deserialization - through controller-like actions - :param serializer: object that supports webob response serialization - through controller-like actions - """ - self.controller = controller - self.serializer = serializer or ResponseSerializer() - self.deserializer = deserializer or RequestDeserializer() - - @webob.dec.wsgify(RequestClass=Request) - def __call__(self, request): - """WSGI method that controls (de)serialization and method dispatch.""" - - try: - action, action_args, accept = self.deserialize_request(request) - except exception.InvalidContentType: - msg = _("Unsupported Content-Type") - return webob.exc.HTTPUnsupportedMediaType(explanation=msg) - except exception.MalformedRequestBody: - msg = _("Malformed request body") - return webob.exc.HTTPBadRequest(explanation=msg) - - action_result = self.execute_action(action, request, **action_args) - try: - return self.serialize_response(action, action_result, accept) - # return unserializable result (typically a webob exc) - except Exception: - return action_result - - def deserialize_request(self, request): - return self.deserializer.deserialize(request) - - def serialize_response(self, action, action_result, accept): - return self.serializer.serialize(action_result, accept, action) - - def execute_action(self, action, request, **action_args): - return self.dispatch(self.controller, action, request, **action_args) - - def dispatch(self, obj, action, *args, **kwargs): - """Find action-specific method on self and call it.""" - try: - method = getattr(obj, action) - except AttributeError: - method = getattr(obj, 'default') - - return method(*args, **kwargs) - - def get_action_args(self, request_environment): - """Parse dictionary created by routes library.""" - try: - args = request_environment['wsgiorg.routing_args'][1].copy() - except Exception: - return {} - - try: - del args['controller'] - except KeyError: - pass - - try: - del args['format'] - except KeyError: - pass - - return args - - -class ActionDispatcher(object): - """Maps method name to local methods through action name.""" - - def dispatch(self, *args, **kwargs): - """Find and call local method.""" - action = kwargs.pop('action', 'default') - action_method = getattr(self, str(action), self.default) - return action_method(*args, **kwargs) - - def default(self, data): - raise NotImplementedError() - - -class DictSerializer(ActionDispatcher): - """Default request body serialization""" - - def serialize(self, data, action='default'): - return self.dispatch(data, action=action) - - def default(self, data): - return "" - - -class JSONDictSerializer(DictSerializer): - """Default JSON request body serialization""" - - def default(self, data): - def sanitizer(obj): - if isinstance(obj, datetime.datetime): - _dtime = obj - datetime.timedelta(microseconds=obj.microsecond) - return _dtime.isoformat() - return unicode(obj) - return jsonutils.dumps(data, default=sanitizer) - - -class XMLDictSerializer(DictSerializer): - - def __init__(self, metadata=None, xmlns=None): - """ - :param metadata: information needed to deserialize xml into - a dictionary. - :param xmlns: XML namespace to include with serialized xml - """ - super(XMLDictSerializer, self).__init__() - self.metadata = metadata or {} - self.xmlns = xmlns - - def default(self, data): - # We expect data to contain a single key which is the XML root. - root_key = data.keys()[0] - doc = minidom.Document() - node = self._to_xml_node(doc, self.metadata, root_key, data[root_key]) - - return self.to_xml_string(node) - - def to_xml_string(self, node, has_atom=False): - self._add_xmlns(node, has_atom) - return node.toprettyxml(indent=' ', encoding='UTF-8') - - #NOTE (ameade): the has_atom should be removed after all of the - # xml serializers and view builders have been updated to the current - # spec that required all responses include the xmlns:atom, the has_atom - # flag is to prevent current tests from breaking - def _add_xmlns(self, node, has_atom=False): - if self.xmlns is not None: - node.setAttribute('xmlns', self.xmlns) - if has_atom: - node.setAttribute('xmlns:atom', "http://www.w3.org/2005/Atom") - - def _to_xml_node(self, doc, metadata, nodename, data): - """Recursive method to convert data members to XML nodes.""" - result = doc.createElement(nodename) - - # Set the xml namespace if one is specified - # TODO(justinsb): We could also use prefixes on the keys - xmlns = metadata.get('xmlns', None) - if xmlns: - result.setAttribute('xmlns', xmlns) - - #TODO(bcwaldon): accomplish this without a type-check - if type(data) is list: - collections = metadata.get('list_collections', {}) - if nodename in collections: - metadata = collections[nodename] - for item in data: - node = doc.createElement(metadata['item_name']) - node.setAttribute(metadata['item_key'], str(item)) - result.appendChild(node) - return result - singular = metadata.get('plurals', {}).get(nodename, None) - if singular is None: - if nodename.endswith('s'): - singular = nodename[:-1] - else: - singular = 'item' - for item in data: - node = self._to_xml_node(doc, metadata, singular, item) - result.appendChild(node) - #TODO(bcwaldon): accomplish this without a type-check - elif type(data) is dict: - collections = metadata.get('dict_collections', {}) - if nodename in collections: - metadata = collections[nodename] - for k, v in data.items(): - node = doc.createElement(metadata['item_name']) - node.setAttribute(metadata['item_key'], str(k)) - text = doc.createTextNode(str(v)) - node.appendChild(text) - result.appendChild(node) - return result - attrs = metadata.get('attributes', {}).get(nodename, {}) - for k, v in data.items(): - if k in attrs: - result.setAttribute(k, str(v)) - else: - node = self._to_xml_node(doc, metadata, k, v) - result.appendChild(node) - else: - # Type is atom - node = doc.createTextNode(str(data)) - result.appendChild(node) - return result - - def _create_link_nodes(self, xml_doc, links): - link_nodes = [] - for link in links: - link_node = xml_doc.createElement('atom:link') - link_node.setAttribute('rel', link['rel']) - link_node.setAttribute('href', link['href']) - if 'type' in link: - link_node.setAttribute('type', link['type']) - link_nodes.append(link_node) - return link_nodes - - -class ResponseHeadersSerializer(ActionDispatcher): - """Default response headers serialization""" - - def serialize(self, response, data, action): - self.dispatch(response, data, action=action) - - def default(self, response, data): - response.status_int = 200 - - -class ResponseSerializer(object): - """Encode the necessary pieces into a response object""" - - def __init__(self, body_serializers=None, headers_serializer=None): - self.body_serializers = { - 'application/xml': XMLDictSerializer(), - 'application/json': JSONDictSerializer(), - } - self.body_serializers.update(body_serializers or {}) - - self.headers_serializer = (headers_serializer or - ResponseHeadersSerializer()) - - def serialize(self, response_data, content_type, action='default'): - """Serialize a dict into a string and wrap in a wsgi.Request object. - - :param response_data: dict produced by the Controller - :param content_type: expected mimetype of serialized response body - - """ - response = webob.Response() - self.serialize_headers(response, response_data, action) - self.serialize_body(response, response_data, content_type, action) - return response - - def serialize_headers(self, response, data, action): - self.headers_serializer.serialize(response, data, action) - - def serialize_body(self, response, data, content_type, action): - response.headers['Content-Type'] = content_type - if data is not None: - serializer = self.get_body_serializer(content_type) - response.body = serializer.serialize(data, action) - - def get_body_serializer(self, content_type): - try: - return self.body_serializers[content_type] - except (KeyError, TypeError): - raise exception.InvalidContentType(content_type=content_type) - - -class RequestHeadersDeserializer(ActionDispatcher): - """Default request headers deserializer""" - - def deserialize(self, request, action): - return self.dispatch(request, action=action) - - def default(self, request): - return {} - - -class RequestDeserializer(object): - """Break up a Request object into more useful pieces.""" - - def __init__(self, body_deserializers=None, headers_deserializer=None, - supported_content_types=None): - - self.supported_content_types = supported_content_types - - self.body_deserializers = { - 'application/xml': XMLDeserializer(), - 'application/json': JSONDeserializer(), - } - self.body_deserializers.update(body_deserializers or {}) - - self.headers_deserializer = (headers_deserializer or - RequestHeadersDeserializer()) - - def deserialize(self, request): - """Extract necessary pieces of the request. - - :param request: Request object - :returns: tuple of (expected controller action name, dictionary of - keyword arguments to pass to the controller, the expected - content type of the response) - - """ - action_args = self.get_action_args(request.environ) - action = action_args.pop('action', None) - - action_args.update(self.deserialize_headers(request, action)) - action_args.update(self.deserialize_body(request, action)) - - accept = self.get_expected_content_type(request) - - return (action, action_args, accept) - - def deserialize_headers(self, request, action): - return self.headers_deserializer.deserialize(request, action) - - def deserialize_body(self, request, action): - if not len(request.body) > 0: - LOG.debug(_("Empty body provided in request")) - return {} - - try: - content_type = request.get_content_type() - except exception.InvalidContentType: - LOG.debug(_("Unrecognized Content-Type provided in request")) - raise - - if content_type is None: - LOG.debug(_("No Content-Type provided in request")) - return {} - - try: - deserializer = self.get_body_deserializer(content_type) - except exception.InvalidContentType: - LOG.debug(_("Unable to deserialize body as provided Content-Type")) - raise - - return deserializer.deserialize(request.body, action) - - def get_body_deserializer(self, content_type): - try: - return self.body_deserializers[content_type] - except (KeyError, TypeError): - raise exception.InvalidContentType(content_type=content_type) - - def get_expected_content_type(self, request): - return request.best_match_content_type(self.supported_content_types) - - def get_action_args(self, request_environment): - """Parse dictionary created by routes library.""" - try: - args = request_environment['wsgiorg.routing_args'][1].copy() - except Exception: - return {} - - try: - del args['controller'] - except KeyError: - pass - - try: - del args['format'] - except KeyError: - pass - - return args - - -class TextDeserializer(ActionDispatcher): - """Default request body deserialization""" - - def deserialize(self, datastring, action='default'): - return self.dispatch(datastring, action=action) - - def default(self, datastring): - return {} - - -class JSONDeserializer(TextDeserializer): - - def _from_json(self, datastring): - try: - return jsonutils.loads(datastring) - except ValueError: - msg = _("cannot understand JSON") - raise exception.MalformedRequestBody(reason=msg) - - def default(self, datastring): - return {'body': self._from_json(datastring)} - - -class XMLDeserializer(TextDeserializer): - - def __init__(self, metadata=None): - """ - :param metadata: information needed to deserialize xml into - a dictionary. - """ - super(XMLDeserializer, self).__init__() - self.metadata = metadata or {} - - def _from_xml(self, datastring): - plurals = set(self.metadata.get('plurals', {})) - - try: - node = xmlutils.safe_minidom_parse_string(datastring).childNodes[0] - return {node.nodeName: self._from_xml_node(node, plurals)} - except expat.ExpatError: - msg = _("cannot understand XML") - raise exception.MalformedRequestBody(reason=msg) - - def _from_xml_node(self, node, listnames): - """Convert a minidom node to a simple Python type. - - :param listnames: list of XML node names whose subnodes should - be considered list items. - - """ - - if len(node.childNodes) == 1 and node.childNodes[0].nodeType == 3: - return node.childNodes[0].nodeValue - elif node.nodeName in listnames: - return [self._from_xml_node(n, listnames) for n in node.childNodes] - else: - result = dict() - for attr in node.attributes.keys(): - result[attr] = node.attributes[attr].nodeValue - for child in node.childNodes: - if child.nodeType != node.TEXT_NODE: - result[child.nodeName] = self._from_xml_node(child, - listnames) - return result - - def find_first_child_named(self, parent, name): - """Search a nodes children for the first child with a given name""" - for node in parent.childNodes: - if node.nodeName == name: - return node - return None - - def find_children_named(self, parent, name): - """Return all of a nodes children who have the given name""" - for node in parent.childNodes: - if node.nodeName == name: - yield node - - def extract_text(self, node): - """Get the text field contained by the given node""" - if len(node.childNodes) == 1: - child = node.childNodes[0] - if child.nodeType == child.TEXT_NODE: - return child.nodeValue - return "" - - def default(self, datastring): - return {'body': self._from_xml(datastring)} diff --git a/api/glazierapi/openstack/common/xmlutils.py b/api/glazierapi/openstack/common/xmlutils.py deleted file mode 100644 index 33700485..00000000 --- a/api/glazierapi/openstack/common/xmlutils.py +++ /dev/null @@ -1,74 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2013 IBM -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from xml.dom import minidom -from xml.parsers import expat -from xml import sax -from xml.sax import expatreader - - -class ProtectedExpatParser(expatreader.ExpatParser): - """An expat parser which disables DTD's and entities by default.""" - - def __init__(self, forbid_dtd=True, forbid_entities=True, - *args, **kwargs): - # Python 2.x old style class - expatreader.ExpatParser.__init__(self, *args, **kwargs) - self.forbid_dtd = forbid_dtd - self.forbid_entities = forbid_entities - - def start_doctype_decl(self, name, sysid, pubid, has_internal_subset): - raise ValueError("Inline DTD forbidden") - - def entity_decl(self, entityName, is_parameter_entity, value, base, - systemId, publicId, notationName): - raise ValueError("<!ENTITY> entity declaration forbidden") - - def unparsed_entity_decl(self, name, base, sysid, pubid, notation_name): - # expat 1.2 - raise ValueError("<!ENTITY> unparsed entity forbidden") - - def external_entity_ref(self, context, base, systemId, publicId): - raise ValueError("<!ENTITY> external entity forbidden") - - def notation_decl(self, name, base, sysid, pubid): - raise ValueError("<!ENTITY> notation forbidden") - - def reset(self): - expatreader.ExpatParser.reset(self) - if self.forbid_dtd: - self._parser.StartDoctypeDeclHandler = self.start_doctype_decl - self._parser.EndDoctypeDeclHandler = None - if self.forbid_entities: - self._parser.EntityDeclHandler = self.entity_decl - self._parser.UnparsedEntityDeclHandler = self.unparsed_entity_decl - self._parser.ExternalEntityRefHandler = self.external_entity_ref - self._parser.NotationDeclHandler = self.notation_decl - try: - self._parser.SkippedEntityHandler = None - except AttributeError: - # some pyexpat versions do not support SkippedEntity - pass - - -def safe_minidom_parse_string(xml_string): - """Parse an XML string using minidom safely. - - """ - try: - return minidom.parseString(xml_string, parser=ProtectedExpatParser()) - except sax.SAXParseException: - raise expat.ExpatError() diff --git a/api/glazierapi/tests/__init__.py b/api/glazierapi/tests/__init__.py deleted file mode 100644 index 7d93825c..00000000 --- a/api/glazierapi/tests/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. diff --git a/api/glazierapi/tests/api/__init__.py b/api/glazierapi/tests/api/__init__.py deleted file mode 100644 index 207fa154..00000000 --- a/api/glazierapi/tests/api/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. \ No newline at end of file diff --git a/api/glazierapi/tests/api/simple_test.py b/api/glazierapi/tests/api/simple_test.py deleted file mode 100644 index 72034e29..00000000 --- a/api/glazierapi/tests/api/simple_test.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import unittest - - -class Test(unittest.TestCase): - def test(self): - assert True diff --git a/api/glazierapi/tests/sanity_tests.py b/api/glazierapi/tests/sanity_tests.py deleted file mode 100644 index 29e0df4f..00000000 --- a/api/glazierapi/tests/sanity_tests.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import unittest2 -from mock import MagicMock - -import glazierapi.api.v1.router as router - - -def my_mock(link, controller, action, conditions): - return [link, controller, action, conditions] - - -def func_mock(): - return True - - -class SanityUnitTests(unittest2.TestCase): - - def test_api(self): - router.webservers = MagicMock(create_resource=func_mock) - router.sessions = MagicMock(create_resource=func_mock) - router.active_directories = MagicMock(create_resource=func_mock) - router.environments = MagicMock(create_resource=func_mock) - mapper = MagicMock(connect=my_mock) - - object = router.API(mapper) - - assert object._router is not None diff --git a/api/glazierapi/utils.py b/api/glazierapi/utils.py deleted file mode 100644 index 26fa6ae1..00000000 --- a/api/glazierapi/utils.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import functools -import logging -from webob import exc -from glazierapi.db.models import Session -from glazierapi.db.session import get_session - -log = logging.getLogger(__name__) - - -def verify_session(func): - @functools.wraps(func) - def __inner(self, request, *args, **kwargs): - if hasattr(request, 'context') and request.context.session: - uw = get_session().query(Session) - configuration_session = uw.get(request.context.session) - - if configuration_session.state != 'open': - log.info('Session is already deployed') - raise exc.HTTPUnauthorized - else: - log.info('No session is supplied') - raise exc.HTTPUnauthorized - return func(self, request, *args, **kwargs) - return __inner diff --git a/api/glazierapi/version.py b/api/glazierapi/version.py deleted file mode 100644 index a0085f36..00000000 --- a/api/glazierapi/version.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from glazierapi.openstack.common import version as common_version - -version_info = common_version.VersionInfo('glazierapi') diff --git a/api/openstack-common.conf b/api/openstack-common.conf deleted file mode 100644 index 2bafe632..00000000 --- a/api/openstack-common.conf +++ /dev/null @@ -1,7 +0,0 @@ -[DEFAULT] - -# The list of modules to copy from openstack-common -modules=setup,wsgi,config,exception,gettextutils,importutils,jsonutils,log,xmlutils,sslutils,service,notifier,local,install_venv_common,version,timeutils,eventlet_backdoor,threadgroup,loopingcall,uuidutils - -# The base module to hold the copy of openstack.common -base=glazierapi \ No newline at end of file diff --git a/api/run_tests.sh b/api/run_tests.sh deleted file mode 100755 index ec7721b3..00000000 --- a/api/run_tests.sh +++ /dev/null @@ -1,123 +0,0 @@ -#!/bin/bash - -function usage { - echo "Usage: $0 [OPTION]..." - echo "Run Glazier API's test suite(s)" - echo "" - echo " -V, --virtual-env Always use virtualenv. Install automatically if not present" - echo " -N, --no-virtual-env Don't use virtualenv. Run tests in local environment" - echo " -f, --force Force a clean re-build of the virtual environment. Useful when dependencies have been added." - echo " -u, --update Update the virtual environment with any newer package versions" - echo " --unittests-only Run unit tests only, exclude functional tests." - echo " -p, --pep8 Just run pep8" - echo " -P, --no-pep8 Don't run static code checks" - echo " -h, --help Print this usage message" - echo "" - echo "Note: with no options specified, the script will try to run the tests in a virtual environment," - echo " If no virtualenv is found, the script will ask if you would like to create one. If you " - echo " prefer to run tests NOT in a virtual environment, simply pass the -N option." - exit -} - -function process_option { - case "$1" in - -h|--help) usage;; - -V|--virtual-env) let always_venv=1; let never_venv=0;; - -N|--no-virtual-env) let always_venv=0; let never_venv=1;; - -p|--pep8) let just_pep8=1;; - -P|--no-pep8) let no_pep8=1;; - -f|--force) let force=1;; - -u|--update) update=1;; - --unittests-only) noseopts="$noseopts --exclude-dir=portas/tests/functional";; - -c|--coverage) noseopts="$noseopts --with-coverage --cover-package=portas";; - -*) noseopts="$noseopts $1";; - *) noseargs="$noseargs $1" - esac -} - -venv=.venv -with_venv=tools/with_venv.sh -always_venv=0 -never_venv=0 -force=0 -noseopts= -noseargs= -wrapper="" -just_pep8=0 -no_pep8=0 -update=0 - -export NOSE_WITH_OPENSTACK=1 -export NOSE_OPENSTACK_COLOR=1 -export NOSE_OPENSTACK_RED=0.05 -export NOSE_OPENSTACK_YELLOW=0.025 -export NOSE_OPENSTACK_SHOW_ELAPSED=1 -export NOSE_OPENSTACK_STDOUT=1 - -for arg in "$@"; do - process_option $arg -done - -function run_tests { - # Cleanup *pyc - ${wrapper} find . -type f -name "*.pyc" -delete - # Just run the test suites in current environment - ${wrapper} rm -f tests.sqlite - ${wrapper} $NOSETESTS -} - -function run_pep8 { - echo "Running pep8 ..." - PEP8_EXCLUDE=".venv,.tox,dist,doc,openstack" - PEP8_OPTIONS="--exclude=$PEP8_EXCLUDE --repeat" - PEP8_IGNORE="--ignore=E125,E126,E711,E712" - PEP8_INCLUDE=". bin/*" - - ${wrapper} pep8 $PEP8_OPTIONS $PEP8_INCLUDE $PEP8_IGNORE -} - - -NOSETESTS="nosetests $noseopts $noseargs" - -if [ $never_venv -eq 0 ] -then - # Remove the virtual environment if --force used - if [ $force -eq 1 ]; then - echo "Cleaning virtualenv..." - rm -rf ${venv} - fi - if [ $update -eq 1 ]; then - echo "Updating virtualenv..." - python tools/install_venv.py - fi - if [ -e ${venv} ]; then - wrapper="${with_venv}" - else - if [ $always_venv -eq 1 ]; then - # Automatically install the virtualenv - python tools/install_venv.py - wrapper="${with_venv}" - else - echo -e "No virtual environment found...create one? (Y/n) \c" - read use_ve - if [ "x$use_ve" = "xY" -o "x$use_ve" = "x" -o "x$use_ve" = "xy" ]; then - # Install the virtualenv and run the test suite in it - python tools/install_venv.py - wrapper=${with_venv} - fi - fi - fi -fi - -if [ $just_pep8 -eq 1 ]; then - run_pep8 - exit -fi - -run_tests || exit - -if [ -z "$noseargs" ]; then - if [ $no_pep8 -eq 0 ]; then - run_pep8 - fi -fi diff --git a/api/setup.cfg b/api/setup.cfg deleted file mode 100644 index 2b3b06e3..00000000 --- a/api/setup.cfg +++ /dev/null @@ -1,33 +0,0 @@ -[build_sphinx] -all_files = 1 -build-dir = doc/build -source-dir = doc/source - -[egg_info] -tag_build = -tag_date = 0 -tag_svn_revision = 0 - -[compile_catalog] -directory = glazierapi/locale -domain = glazierapi - -[update_catalog] -domain = glazierapi -output_dir = glazierapi/locale -input_file = glazierapi/locale/glazierapi.pot - -[extract_messages] -keywords = _ gettext ngettext l_ lazy_gettext -mapping_file = babel.cfg -output_file = glazierapi/locale/glazierapi.pot - -[nosetests] -# NOTE(jkoelker) To run the test suite under nose install the following -# coverage http://pypi.python.org/pypi/coverage -# tissue http://pypi.python.org/pypi/tissue (pep8 checker) -# openstack-nose https://github.com/jkoelker/openstack-nose -verbosity=2 -cover-package = portas -cover-html = true -cover-erase = true \ No newline at end of file diff --git a/api/setup.py b/api/setup.py deleted file mode 100644 index 01d3ce91..00000000 --- a/api/setup.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/python -# -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import setuptools - -from glazierapi.openstack.common import setup - -requires = setup.parse_requirements() -depend_links = setup.parse_dependency_links() -project = 'glazierapi' - -setuptools.setup( - name=project, - version=setup.get_version(project, '2013.1'), - description='The Glazier Project API', - license='Apache License (2.0)', - author='Mirantis, Inc', - author_email='smelikyan@mirantis.com', - url='http://glazierapi.mirantis.com/', - packages=setuptools.find_packages(exclude=['bin']), - test_suite='nose.collector', - cmdclass=setup.get_cmdclass(), - include_package_data=True, - install_requires=requires, - dependency_links=depend_links, - classifiers=[ - 'Development Status :: 4 - Beta', - 'License :: OSI Approved :: Apache Software License', - 'Operating System :: POSIX :: Linux', - 'Programming Language :: Python :: 2.7', - 'Environment :: No Input/Output (Daemon)', - 'Environment :: OpenStack', - ], - scripts=['bin/glazierapi-api'], - py_modules=[] -) diff --git a/api/tools/install_venv.py b/api/tools/install_venv.py deleted file mode 100644 index ecf3c45f..00000000 --- a/api/tools/install_venv.py +++ /dev/null @@ -1,75 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Copyright 2010 OpenStack LLC. -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Installation script for Glance's development virtualenv -""" - -import os -import subprocess -import sys - -import install_venv_common as install_venv - - -def print_help(): - help = """ - Glazier API development environment setup is complete. - - Glazier API development uses virtualenv to track and manage Python dependencies - while in development and testing. - - To activate the Glazier API virtualenv for the extent of your current shell session - you can run: - - $ source .venv/bin/activate - - Or, if you prefer, you can run commands in the virtualenv on a case by case - basis by running: - - $ tools/with_venv.sh <your command> - - Also, make test will automatically use the virtualenv. - """ - print help - - -def main(argv): - root = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) - venv = os.path.join(root, '.venv') - pip_requires = os.path.join(root, 'tools', 'pip-requires') - test_requires = os.path.join(root, 'tools', 'test-requires') - py_version = "python%s.%s" % (sys.version_info[0], sys.version_info[1]) - project = 'glazierapi' - install = install_venv.InstallVenv(root, venv, pip_requires, test_requires, - py_version, project) - options = install.parse_args(argv) - install.check_python_version() - install.check_dependencies() - install.create_virtualenv(no_site_packages=options.no_site_packages) - install.install_dependencies() - install.run_command([os.path.join(venv, 'bin/python'), - 'setup.py', 'develop']) - install.post_process() - print_help() - -if __name__ == '__main__': - main(sys.argv) diff --git a/api/tools/install_venv_common.py b/api/tools/install_venv_common.py deleted file mode 100644 index fd9076f0..00000000 --- a/api/tools/install_venv_common.py +++ /dev/null @@ -1,219 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2013 OpenStack, LLC -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides methods needed by installation script for OpenStack development -virtual environments. - -Synced in from openstack-common -""" - -import argparse -import os -import subprocess -import sys - - -class InstallVenv(object): - - def __init__(self, root, venv, pip_requires, test_requires, py_version, - project): - self.root = root - self.venv = venv - self.pip_requires = pip_requires - self.test_requires = test_requires - self.py_version = py_version - self.project = project - - def die(self, message, *args): - print >> sys.stderr, message % args - sys.exit(1) - - def check_python_version(self): - if sys.version_info < (2, 6): - self.die("Need Python Version >= 2.6") - - def run_command_with_code(self, cmd, redirect_output=True, - check_exit_code=True): - """Runs a command in an out-of-process shell. - - Returns the output of that command. Working directory is self.root. - """ - if redirect_output: - stdout = subprocess.PIPE - else: - stdout = None - - proc = subprocess.Popen(cmd, cwd=self.root, stdout=stdout) - output = proc.communicate()[0] - if check_exit_code and proc.returncode != 0: - self.die('Command "%s" failed.\n%s', ' '.join(cmd), output) - return (output, proc.returncode) - - def run_command(self, cmd, redirect_output=True, check_exit_code=True): - return self.run_command_with_code(cmd, redirect_output, - check_exit_code)[0] - - def get_distro(self): - if (os.path.exists('/etc/fedora-release') or - os.path.exists('/etc/redhat-release')): - return Fedora(self.root, self.venv, self.pip_requires, - self.test_requires, self.py_version, self.project) - else: - return Distro(self.root, self.venv, self.pip_requires, - self.test_requires, self.py_version, self.project) - - def check_dependencies(self): - self.get_distro().install_virtualenv() - - def create_virtualenv(self, no_site_packages=True): - """Creates the virtual environment and installs PIP. - - Creates the virtual environment and installs PIP only into the - virtual environment. - """ - if not os.path.isdir(self.venv): - print 'Creating venv...', - if no_site_packages: - self.run_command(['virtualenv', '-q', '--no-site-packages', - self.venv]) - else: - self.run_command(['virtualenv', '-q', self.venv]) - print 'done.' - print 'Installing pip in venv...', - if not self.run_command(['tools/with_venv.sh', 'easy_install', - 'pip>1.0']).strip(): - self.die("Failed to install pip.") - print 'done.' - else: - print "venv already exists..." - pass - - def pip_install(self, *args): - self.run_command(['tools/with_venv.sh', - 'pip', 'install', '--upgrade'] + list(args), - redirect_output=False) - - def install_dependencies(self): - print 'Installing dependencies with pip (this can take a while)...' - - # First things first, make sure our venv has the latest pip and - # distribute. - # NOTE: we keep pip at version 1.1 since the most recent version causes - # the .venv creation to fail. See: - # https://bugs.launchpad.net/nova/+bug/1047120 - self.pip_install('pip==1.1') - self.pip_install('distribute') - - # Install greenlet by hand - just listing it in the requires file does - # not - # get it installed in the right order - self.pip_install('greenlet') - - self.pip_install('-r', self.pip_requires) - self.pip_install('-r', self.test_requires) - - def post_process(self): - self.get_distro().post_process() - - def parse_args(self, argv): - """Parses command-line arguments.""" - parser = argparse.ArgumentParser() - parser.add_argument('-n', '--no-site-packages', - action='store_true', - help="Do not inherit packages from global Python " - "install") - return parser.parse_args(argv[1:]) - - -class Distro(InstallVenv): - - def check_cmd(self, cmd): - return bool(self.run_command(['which', cmd], - check_exit_code=False).strip()) - - def install_virtualenv(self): - if self.check_cmd('virtualenv'): - return - - if self.check_cmd('easy_install'): - print 'Installing virtualenv via easy_install...', - if self.run_command(['easy_install', 'virtualenv']): - print 'Succeeded' - return - else: - print 'Failed' - - self.die('ERROR: virtualenv not found.\n\n%s development' - ' requires virtualenv, please install it using your' - ' favorite package management tool' % self.project) - - def post_process(self): - """Any distribution-specific post-processing gets done here. - - In particular, this is useful for applying patches to code inside - the venv. - """ - pass - - -class Fedora(Distro): - """This covers all Fedora-based distributions. - - Includes: Fedora, RHEL, CentOS, Scientific Linux - """ - - def check_pkg(self, pkg): - return self.run_command_with_code(['rpm', '-q', pkg], - check_exit_code=False)[1] == 0 - - def yum_install(self, pkg, **kwargs): - print "Attempting to install '%s' via yum" % pkg - self.run_command(['sudo', 'yum', 'install', '-y', pkg], **kwargs) - - def apply_patch(self, originalfile, patchfile): - self.run_command(['patch', originalfile, patchfile]) - - def install_virtualenv(self): - if self.check_cmd('virtualenv'): - return - - if not self.check_pkg('python-virtualenv'): - self.yum_install('python-virtualenv', check_exit_code=False) - - super(Fedora, self).install_virtualenv() - - def post_process(self): - """Workaround for a bug in eventlet. - - This currently affects RHEL6.1, but the fix can safely be - applied to all RHEL and Fedora distributions. - - This can be removed when the fix is applied upstream. - - Nova: https://bugs.launchpad.net/nova/+bug/884915 - Upstream: https://bitbucket.org/which_linden/eventlet/issue/89 - """ - - # Install "patch" program if it's not there - if not self.check_pkg('patch'): - self.yum_install('patch') - - # Apply the eventlet patch - self.apply_patch(os.path.join(self.venv, 'lib', self.py_version, - 'site-packages', - 'eventlet/green/subprocess.py'), - 'contrib/redhat-eventlet.patch') diff --git a/api/tools/pip-requires b/api/tools/pip-requires deleted file mode 100644 index 2b71bd97..00000000 --- a/api/tools/pip-requires +++ /dev/null @@ -1,31 +0,0 @@ -Babel -SQLAlchemy>=0.7,<=0.7.9 -anyjson -eventlet>=0.9.12 -PasteDeploy -routes -WebOb>=1.2 -wsgiref -argparse -boto -sqlalchemy-migrate>=0.7 -httplib2 -kombu -pycrypto>=2.1.0alpha1 -iso8601>=0.1.4 -amqplib - -# Note you will need gcc buildtools installed and must -# have installed libxml headers for lxml to be successfully -# installed using pip, therefore you will need to install the -# libxml2-dev and libxslt-dev Ubuntu packages. -lxml - -# For paste.util.template used in keystone.common.template -Paste - -passlib -jsonschema -python-keystoneclient>=0.2.0 - -http://tarballs.openstack.org/oslo-config/oslo-config-2013.1b4.tar.gz#egg=oslo-config diff --git a/api/tools/test-requires b/api/tools/test-requires deleted file mode 100644 index a7066f1e..00000000 --- a/api/tools/test-requires +++ /dev/null @@ -1,20 +0,0 @@ -# Packages needed for dev testing -distribute>=0.6.24 - -# Needed for testing -unittest2 -coverage -fixtures>=0.3.12 -mox -nose -nose-exclude -openstack.nose_plugin>=0.7 -nosehtmloutput>=0.0.3 -pep8==1.3.3 -sphinx>=1.1.2 -requests -testtools>=0.9.22 - -# Optional packages that should be installed when testing -xattr>=0.6.0 -pysendfile==2.0.0 \ No newline at end of file diff --git a/api/tools/with_venv.sh b/api/tools/with_venv.sh deleted file mode 100755 index c8d2940f..00000000 --- a/api/tools/with_venv.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -TOOLS=`dirname $0` -VENV=$TOOLS/../.venv -source $VENV/bin/activate && $@ diff --git a/api/tox.ini b/api/tox.ini deleted file mode 100644 index 47fc9d4d..00000000 --- a/api/tox.ini +++ /dev/null @@ -1,46 +0,0 @@ -[tox] -envlist = py27,pep8 - -[testenv] -setenv = VIRTUAL_ENV={envdir} - NOSE_WITH_OPENSTACK=1 - NOSE_OPENSTACK_COLOR=1 - NOSE_OPENSTACK_RED=0.05 - NOSE_OPENSTACK_YELLOW=0.025 - NOSE_OPENSTACK_SHOW_ELAPSED=1 -deps = -r{toxinidir}/tools/pip-requires - -r{toxinidir}/tools/test-requires -commands = nosetests - -[testenv:pep8] -deps = pep8==1.3.3 -commands = pep8 --repeat --show-source glazierapi setup.py - -[testenv:venv] -commands = {posargs} - -[testenv:cover] -commands = nosetests --cover-erase --cover-package=glazierapi --with-xcoverage - -[tox:jenkins] -downloadcache = ~/cache/pip - -[testenv:jenkins26] -basepython = python2.6 -setenv = NOSE_WITH_XUNIT=1 -deps = file://{toxinidir}/.cache.bundle - -[testenv:jenkins27] -basepython = python2.7 -setenv = NOSE_WITH_XUNIT=1 -deps = file://{toxinidir}/.cache.bundle - -[testenv:jenkinscover] -deps = file://{toxinidir}/.cache.bundle -setenv = NOSE_WITH_XUNIT=1 -commands = nosetests --cover-erase --cover-package=glazierapi --with-xcoverage - -[testenv:jenkinsvenv] -deps = file://{toxinidir}/.cache.bundle -setenv = NOSE_WITH_XUNIT=1 -commands = {posargs} diff --git a/conductor/.gitignore b/conductor/.gitignore deleted file mode 100644 index 61331307..00000000 --- a/conductor/.gitignore +++ /dev/null @@ -1,20 +0,0 @@ -#IntelJ Idea -.idea/ - -#virtualenv -.venv/ - -#Build results -build/ -dist/ -*.egg-info/ - -#Python -*.pyc - -#Translation build -*.mo -*.pot - -#SQLite Database files -*.sqlite \ No newline at end of file diff --git a/conductor/README.rst b/conductor/README.rst deleted file mode 100644 index 38cfa96f..00000000 --- a/conductor/README.rst +++ /dev/null @@ -1,8 +0,0 @@ -Glazier Conductor README -======================== -Conductor is an Glazier orchestration engine that transforms object model sent by -REST API service into a series of Heat and Glazier-Agent commands - -SEE ALSO --------- -* `Keero <http://keero.mirantis.com>`__ diff --git a/conductor/babel.cfg b/conductor/babel.cfg deleted file mode 100644 index efceab81..00000000 --- a/conductor/babel.cfg +++ /dev/null @@ -1 +0,0 @@ -[python: **.py] diff --git a/conductor/bin/conductor b/conductor/bin/conductor deleted file mode 100644 index e92f28a8..00000000 --- a/conductor/bin/conductor +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys - - -from conductor import config -from conductor.openstack.common import log -from conductor.openstack.common import service -from conductor.app import ConductorWorkflowService - -if __name__ == '__main__': - try: - config.parse_args() - log.setup('conductor') - launcher = service.ServiceLauncher() - launcher.launch_service(ConductorWorkflowService()) - launcher.wait() - except RuntimeError, e: - sys.stderr.write("ERROR: %s\n" % e) - sys.exit(1) diff --git a/conductor/conductor/__init__.py b/conductor/conductor/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/conductor/conductor/app.py b/conductor/conductor/app.py deleted file mode 100644 index e70f59e8..00000000 --- a/conductor/conductor/app.py +++ /dev/null @@ -1,105 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import datetime -import glob -import sys -import traceback - -import anyjson -from conductor.openstack.common import service -from workflow import Workflow -from commands.dispatcher import CommandDispatcher -from openstack.common import log as logging -from config import Config -import reporting -import rabbitmq - -import windows_agent -import cloud_formation - -config = Config(sys.argv[1] if len(sys.argv) > 1 else None) - -log = logging.getLogger(__name__) - - -def task_received(task, message_id): - with rabbitmq.RmqClient() as rmqclient: - try: - log.info('Starting processing task {0}: {1}'.format( - message_id, anyjson.dumps(task))) - reporter = reporting.Reporter(rmqclient, message_id, task['id']) - - command_dispatcher = CommandDispatcher( - task['name'], rmqclient, task['token'], task['tenant_id']) - workflows = [] - for path in glob.glob("data/workflows/*.xml"): - log.debug('Loading XML {0}'.format(path)) - workflow = Workflow(path, task, command_dispatcher, config, - reporter) - workflows.append(workflow) - - while True: - try: - while True: - result = False - for workflow in workflows: - if workflow.execute(): - result = True - if not result: - break - if not command_dispatcher.execute_pending(): - break - except Exception as ex: - log.exception(ex) - break - - command_dispatcher.close() - finally: - del task['token'] - result_msg = rabbitmq.Message() - result_msg.body = task - result_msg.id = message_id - - rmqclient.send(message=result_msg, key='task-results') - log.info('Finished processing task {0}. Result = {1}'.format( - message_id, anyjson.dumps(task))) - - -class ConductorWorkflowService(service.Service): - def __init__(self): - super(ConductorWorkflowService, self).__init__() - - def start(self): - super(ConductorWorkflowService, self).start() - self.tg.add_thread(self._start_rabbitmq) - - def stop(self): - super(ConductorWorkflowService, self).stop() - - def _start_rabbitmq(self): - while True: - try: - with rabbitmq.RmqClient() as rmq: - rmq.declare('tasks', 'tasks') - rmq.declare('task-results') - with rmq.open('tasks') as subscription: - while True: - msg = subscription.get_message() - self.tg.add_thread( - task_received, msg.body, msg.id) - except Exception as ex: - log.exception(ex) - diff --git a/conductor/conductor/cloud_formation.py b/conductor/conductor/cloud_formation.py deleted file mode 100644 index 7a47e56e..00000000 --- a/conductor/conductor/cloud_formation.py +++ /dev/null @@ -1,127 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import base64 -import config -import random -import string -import time - -import xml_code_engine - - -def update_cf_stack(engine, context, body, template, - mappings, arguments, **kwargs): - command_dispatcher = context['/commandDispatcher'] - - callback = lambda result: engine.evaluate_content( - body.find('success'), context) - - command_dispatcher.execute( - name='cf', command='CreateOrUpdate', template=template, - mappings=mappings, arguments=arguments, callback=callback) - - -def delete_cf_stack(engine, context, body, **kwargs): - command_dispatcher = context['/commandDispatcher'] - - callback = lambda result: engine.evaluate_content( - body.find('success'), context) - - command_dispatcher.execute( - name='cf', command='Delete', callback=callback) - - -def prepare_user_data(context, hostname, service, unit, - template='Default', **kwargs): - settings = config.CONF.rabbitmq - - with open('data/init.ps1') as init_script_file: - with open('data/templates/agent-config/{0}.template'.format( - template)) as template_file: - init_script = init_script_file.read() - template_data = template_file.read() - - replacements = { - '%RABBITMQ_HOST%': settings.host, - '%RABBITMQ_INPUT_QUEUE%': '-'.join( - [str(context['/dataSource']['name']), - str(service), str(unit)]).lower(), - '%RESULT_QUEUE%': '-execution-results-{0}'.format( - str(context['/dataSource']['name'])).lower(), - '%RABBITMQ_USER%': settings.login, - '%RABBITMQ_PASSWORD%': settings.password, - '%RABBITMQ_VHOST%': settings.virtual_host - } - - template_data = set_config_params(template_data, replacements) - - init_script = init_script.replace( - '%WINDOWS_AGENT_CONFIG_BASE64%', - base64.b64encode(template_data)) - - init_script = init_script.replace('%INTERNAL_HOSTNAME%', hostname) - - return init_script - - -def set_config_params(template_data, replacements): - for key in replacements: - template_data = template_data.replace(key, replacements[key]) - return template_data - - -counter = 0 - - -def int2base(x, base): - digs = string.digits + string.lowercase - if x < 0: - sign = -1 - elif x == 0: - return '0' - else: - sign = 1 - x *= sign - digits = [] - while x: - digits.append(digs[x % base]) - x /= base - if sign < 0: - digits.append('-') - digits.reverse() - return ''.join(digits) - - -def generate_hostname(**kwargs): - global counter - prefix = ''.join(random.choice(string.lowercase) for _ in range(5)) - timestamp = int2base(int(time.time() * 1000), 36)[:8] - suffix = int2base(counter, 36) - counter = (counter + 1) % 1296 - return prefix + timestamp + suffix - - -xml_code_engine.XmlCodeEngine.register_function( - update_cf_stack, "update-cf-stack") - -xml_code_engine.XmlCodeEngine.register_function( - delete_cf_stack, "delete-cf-stack") - -xml_code_engine.XmlCodeEngine.register_function( - prepare_user_data, "prepare-user-data") - -xml_code_engine.XmlCodeEngine.register_function( - generate_hostname, "generate-hostname") diff --git a/conductor/conductor/commands/__init__.py b/conductor/conductor/commands/__init__.py deleted file mode 100644 index 1fa2c573..00000000 --- a/conductor/conductor/commands/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import command diff --git a/conductor/conductor/commands/cloud_formation.py b/conductor/conductor/commands/cloud_formation.py deleted file mode 100644 index 9cc7a1ca..00000000 --- a/conductor/conductor/commands/cloud_formation.py +++ /dev/null @@ -1,188 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import anyjson -import eventlet -import types -import jsonpath - -from conductor.openstack.common import log as logging -import conductor.helpers -from command import CommandBase -import conductor.config -from heatclient.client import Client -import heatclient.exc -from keystoneclient.v2_0 import client as ksclient - -log = logging.getLogger(__name__) - - -class HeatExecutor(CommandBase): - def __init__(self, stack, token, tenant_id): - self._update_pending_list = [] - self._delete_pending_list = [] - self._stack = stack - settings = conductor.config.CONF.heat - - client = ksclient.Client(endpoint=settings.auth_url) - auth_data = client.tokens.authenticate( - tenant_id=tenant_id, - token=token) - - scoped_token = auth_data.id - - heat_url = jsonpath.jsonpath( - auth_data.serviceCatalog, - "$[?(@.name == 'heat')].endpoints[0].publicURL")[0] - - self._heat_client = Client( - '1', - heat_url, - token_only=True, - token=scoped_token) - - def execute(self, command, callback, **kwargs): - log.debug('Got command {0} on stack {1}'.format(command, self._stack)) - - if command == 'CreateOrUpdate': - return self._execute_create_update( - kwargs['template'], - kwargs['mappings'], - kwargs['arguments'], - callback) - elif command == 'Delete': - return self._execute_delete(callback) - - def _execute_create_update(self, template, mappings, arguments, callback): - with open('data/templates/cf/%s.template' % template) as template_file: - template_data = template_file.read() - - template_data = conductor.helpers.transform_json( - anyjson.loads(template_data), mappings) - - self._update_pending_list.append({ - 'template': template_data, - 'arguments': arguments, - 'callback': callback - }) - - def _execute_delete(self, callback): - self._delete_pending_list.append({ - 'callback': callback - }) - - def has_pending_commands(self): - return len(self._update_pending_list) + \ - len(self._delete_pending_list) > 0 - - def execute_pending(self): - r1 = self._execute_pending_updates() - r2 = self._execute_pending_deletes() - return r1 or r2 - - def _execute_pending_updates(self): - if not len(self._update_pending_list): - return False - - template, arguments = self._get_current_template() - stack_exists = (template != {}) - - for t in self._update_pending_list: - template = conductor.helpers.merge_dicts( - template, t['template'], max_levels=2) - arguments = conductor.helpers.merge_dicts( - arguments, t['arguments'], max_levels=1) - - log.info( - 'Executing heat template {0} with arguments {1} on stack {2}' - .format(anyjson.dumps(template), arguments, self._stack)) - - if stack_exists: - self._heat_client.stacks.update( - stack_id=self._stack, - parameters=arguments, - template=template) - log.debug( - 'Waiting for the stack {0} to be update'.format(self._stack)) - self._wait_state('UPDATE_COMPLETE') - log.info('Stack {0} updated'.format(self._stack)) - else: - self._heat_client.stacks.create( - stack_name=self._stack, - parameters=arguments, - template=template) - log.debug('Waiting for the stack {0} to be create'.format( - self._stack)) - self._wait_state('CREATE_COMPLETE') - log.info('Stack {0} created'.format(self._stack)) - - pending_list = self._update_pending_list - self._update_pending_list = [] - - for item in pending_list: - item['callback'](True) - - return True - - def _execute_pending_deletes(self): - if not len(self._delete_pending_list): - return False - - log.debug('Deleting stack {0}'.format(self._stack)) - try: - self._heat_client.stacks.delete( - stack_id=self._stack) - log.debug( - 'Waiting for the stack {0} to be deleted'.format(self._stack)) - self._wait_state(['DELETE_COMPLETE', '']) - log.info('Stack {0} deleted'.format(self._stack)) - except Exception as ex: - log.exception(ex) - - pending_list = self._delete_pending_list - self._delete_pending_list = [] - - for item in pending_list: - item['callback'](True) - return True - - def _get_current_template(self): - try: - stack_info = self._heat_client.stacks.get(stack_id=self._stack) - template = self._heat_client.stacks.template( - stack_id='{0}/{1}'.format(stack_info.stack_name, stack_info.id)) - return template, stack_info.parameters - except heatclient.exc.HTTPNotFound: - return {}, {} - - def _wait_state(self, state): - if isinstance(state, types.ListType): - states = state - else: - states = [state] - - while True: - try: - status = self._heat_client.stacks.get( - stack_id=self._stack).stack_status - except heatclient.exc.HTTPNotFound: - status = '' - - if 'IN_PROGRESS' in status: - eventlet.sleep(1) - continue - if status not in states: - raise EnvironmentError() - return diff --git a/conductor/conductor/commands/command.py b/conductor/conductor/commands/command.py deleted file mode 100644 index 606c7293..00000000 --- a/conductor/conductor/commands/command.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -class CommandBase(object): - def execute(self, **kwargs): - pass - - def execute_pending(self): - return False - - def has_pending_commands(self): - return False - - def close(self): - pass diff --git a/conductor/conductor/commands/dispatcher.py b/conductor/conductor/commands/dispatcher.py deleted file mode 100644 index 37014459..00000000 --- a/conductor/conductor/commands/dispatcher.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import command -import cloud_formation -import windows_agent - - -class CommandDispatcher(command.CommandBase): - def __init__(self, environment, rmqclient, token, tenant_id): - self._command_map = { - 'cf': cloud_formation.HeatExecutor(environment, token, tenant_id), - 'agent': windows_agent.WindowsAgentExecutor( - environment, rmqclient) - } - - def execute(self, name, **kwargs): - self._command_map[name].execute(**kwargs) - - def execute_pending(self): - result = False - for command in self._command_map.values(): - result |= command.execute_pending() - - return result - - def has_pending_commands(self): - result = False - for command in self._command_map.values(): - result |= command.has_pending_commands() - - return result - - def close(self): - for t in self._command_map.values(): - t.close() diff --git a/conductor/conductor/commands/windows_agent.py b/conductor/conductor/commands/windows_agent.py deleted file mode 100644 index ea66b718..00000000 --- a/conductor/conductor/commands/windows_agent.py +++ /dev/null @@ -1,61 +0,0 @@ -import json -import uuid - -from conductor.openstack.common import log as logging -from conductor.rabbitmq import Message -import conductor.helpers -from command import CommandBase - -log = logging.getLogger(__name__) - - -class WindowsAgentExecutor(CommandBase): - def __init__(self, stack, rmqclient): - self._stack = stack - self._rmqclient = rmqclient - self._pending_list = [] - self._results_queue = '-execution-results-%s' % str(stack).lower() - rmqclient.declare(self._results_queue) - - def execute(self, template, mappings, host, service, callback): - with open('data/templates/agent/%s.template' % template) as file: - template_data = file.read() - - template_data = conductor.helpers.transform_json( - json.loads(template_data), mappings) - - id = str(uuid.uuid4()).lower() - host = ('%s-%s-%s' % (self._stack, service, host)).lower() - self._pending_list.append({ - 'id': id, - 'callback': callback - }) - - msg = Message() - msg.body = template_data - msg.id = id - self._rmqclient.declare(host) - self._rmqclient.send(message=msg, key=host) - log.info('Sending RMQ message {0} to {1} with id {2}'.format( - template_data, host, id)) - - def has_pending_commands(self): - return len(self._pending_list) > 0 - - def execute_pending(self): - if not self.has_pending_commands(): - return False - - with self._rmqclient.open(self._results_queue) as subscription: - while self.has_pending_commands(): - msg = subscription.get_message() - msg_id = msg.id.lower() - item, index = conductor.helpers.find( - lambda t: t['id'] == msg_id, self._pending_list) - if item: - self._pending_list.pop(index) - item['callback'](msg.body) - - return True - - diff --git a/conductor/conductor/config.py b/conductor/conductor/config.py deleted file mode 100644 index bb804dab..00000000 --- a/conductor/conductor/config.py +++ /dev/null @@ -1,210 +0,0 @@ -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Routines for configuring Glance -""" - -import logging -import logging.config -import logging.handlers -import os -import sys - -from oslo.config import cfg -from paste import deploy - -from conductor.version import version_info as version -from ConfigParser import SafeConfigParser - -paste_deploy_opts = [ - cfg.StrOpt('flavor'), - cfg.StrOpt('config_file'), -] - -rabbit_opts = [ - cfg.StrOpt('host', default='localhost'), - cfg.IntOpt('port', default=5672), - cfg.StrOpt('login', default='guest'), - cfg.StrOpt('password', default='guest'), - cfg.StrOpt('virtual_host', default='/'), -] - -heat_opts = [ - cfg.StrOpt('auth_url'), -] - -CONF = cfg.CONF -CONF.register_opts(paste_deploy_opts, group='paste_deploy') -CONF.register_opts(rabbit_opts, group='rabbitmq') -CONF.register_opts(heat_opts, group='heat') - - -CONF.import_opt('verbose', 'conductor.openstack.common.log') -CONF.import_opt('debug', 'conductor.openstack.common.log') -CONF.import_opt('log_dir', 'conductor.openstack.common.log') -CONF.import_opt('log_file', 'conductor.openstack.common.log') -CONF.import_opt('log_config', 'conductor.openstack.common.log') -CONF.import_opt('log_format', 'conductor.openstack.common.log') -CONF.import_opt('log_date_format', 'conductor.openstack.common.log') -CONF.import_opt('use_syslog', 'conductor.openstack.common.log') -CONF.import_opt('syslog_log_facility', 'conductor.openstack.common.log') - - -def parse_args(args=None, usage=None, default_config_files=None): - CONF(args=args, - project='conductor', - version=version.cached_version_string(), - usage=usage, - default_config_files=default_config_files) - - -def setup_logging(): - """ - Sets up the logging options for a log with supplied name - """ - - if CONF.log_config: - # Use a logging configuration file for all settings... - if os.path.exists(CONF.log_config): - logging.config.fileConfig(CONF.log_config) - return - else: - raise RuntimeError("Unable to locate specified logging " - "config file: %s" % CONF.log_config) - - root_logger = logging.root - if CONF.debug: - root_logger.setLevel(logging.DEBUG) - elif CONF.verbose: - root_logger.setLevel(logging.INFO) - else: - root_logger.setLevel(logging.WARNING) - - formatter = logging.Formatter(CONF.log_format, CONF.log_date_format) - - if CONF.use_syslog: - try: - facility = getattr(logging.handlers.SysLogHandler, - CONF.syslog_log_facility) - except AttributeError: - raise ValueError(_("Invalid syslog facility")) - - handler = logging.handlers.SysLogHandler(address='/dev/log', - facility=facility) - elif CONF.log_file: - logfile = CONF.log_file - if CONF.log_dir: - logfile = os.path.join(CONF.log_dir, logfile) - handler = logging.handlers.WatchedFileHandler(logfile) - else: - handler = logging.StreamHandler(sys.stdout) - - handler.setFormatter(formatter) - root_logger.addHandler(handler) - - -def _get_deployment_flavor(): - """ - Retrieve the paste_deploy.flavor config item, formatted appropriately - for appending to the application name. - """ - flavor = CONF.paste_deploy.flavor - return '' if not flavor else ('-' + flavor) - - -def _get_paste_config_path(): - paste_suffix = '-paste.ini' - conf_suffix = '.conf' - if CONF.config_file: - # Assume paste config is in a paste.ini file corresponding - # to the last config file - path = CONF.config_file[-1].replace(conf_suffix, paste_suffix) - else: - path = CONF.prog + '-paste.ini' - return CONF.find_file(os.path.basename(path)) - - -def _get_deployment_config_file(): - """ - Retrieve the deployment_config_file config item, formatted as an - absolute pathname. - """ - path = CONF.paste_deploy.config_file - if not path: - path = _get_paste_config_path() - if not path: - msg = "Unable to locate paste config file for %s." % CONF.prog - raise RuntimeError(msg) - return os.path.abspath(path) - - -def load_paste_app(app_name=None): - """ - Builds and returns a WSGI app from a paste config file. - - We assume the last config file specified in the supplied ConfigOpts - object is the paste config file. - - :param app_name: name of the application to load - - :raises RuntimeError when config file cannot be located or application - cannot be loaded from config file - """ - if app_name is None: - app_name = CONF.prog - - # append the deployment flavor to the application name, - # in order to identify the appropriate paste pipeline - app_name += _get_deployment_flavor() - - conf_file = _get_deployment_config_file() - - try: - logger = logging.getLogger(__name__) - logger.debug(_("Loading %(app_name)s from %(conf_file)s"), - {'conf_file': conf_file, 'app_name': app_name}) - - app = deploy.loadapp("config:%s" % conf_file, name=app_name) - - # Log the options used when starting if we're in debug mode... - if CONF.debug: - CONF.log_opt_values(logger, logging.DEBUG) - - return app - except (LookupError, ImportError), e: - msg = _("Unable to load %(app_name)s from " - "configuration file %(conf_file)s." - "\nGot: %(e)r") % locals() - logger.error(msg) - raise RuntimeError(msg) - - -class Config(object): - CONFIG_PATH = './etc/app.config' - - def __init__(self, filename=None): - self.config = SafeConfigParser() - self.config.read(filename or self.CONFIG_PATH) - - def get_setting(self, section, name, default=None): - if not self.config.has_option(section, name): - return default - return self.config.get(section, name) - - def __getitem__(self, item): - parts = item.rsplit('.', 1) - return self.get_setting( - parts[0] if len(parts) == 2 else 'DEFAULT', parts[-1]) diff --git a/conductor/conductor/function_context.py b/conductor/conductor/function_context.py deleted file mode 100644 index e210fd7b..00000000 --- a/conductor/conductor/function_context.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -class Context(object): - def __init__(self, parent=None): - self._parent = parent - self._data = None - - def _get_data(self): - if self._data is None: - self._data = {} if self._parent is None \ - else self._parent._get_data().copy() - return self._data - - def __getitem__(self, item): - context, path = self._parseContext(item) - return context._get_data().get(path) - - def __setitem__(self, key, value): - context, path = self._parseContext(key) - context._get_data()[path] = value - - def _parseContext(self, path): - context = self - index = 0 - for c in path: - if c == ':' and context._parent is not None: - context = context._parent - elif c == '/': - while context._parent is not None: - context = context._parent - else: - break - - index += 1 - - return context, path[index:] - - def assign_from(self, context, copy=False): - self._parent = context._parent - self._data = context._data - if copy and self._data is not None: - self._data = self._data.copy() - - @property - def parent(self): - return self._parent - - def __str__(self): - if self._data is not None: - return str(self._data) - if self._parent: - return str(self._parent) - return str({}) diff --git a/conductor/conductor/helpers.py b/conductor/conductor/helpers.py deleted file mode 100644 index da196560..00000000 --- a/conductor/conductor/helpers.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import types - - -def transform_json(json, mappings): - if isinstance(json, types.ListType): - return [transform_json(t, mappings) for t in json] - - if isinstance(json, types.DictionaryType): - result = {} - for key, value in json.items(): - result[transform_json(key, mappings)] = \ - transform_json(value, mappings) - return result - - if isinstance(json, types.StringTypes) and json.startswith('$'): - value = mappings.get(json[1:]) - if value is not None: - return value - - return json - - -def merge_dicts(dict1, dict2, max_levels=0): - result = {} - for key, value in dict1.items(): - result[key] = value - if key in dict2: - other_value = dict2[key] - if max_levels == 1 or not isinstance( - other_value, types.DictionaryType): - result[key] = other_value - else: - result[key] = merge_dicts( - value, other_value, - 0 if max_levels == 0 else max_levels - 1) - for key, value in dict2.items(): - if key not in result: - result[key] = value - return result - - -def find(f, seq): - """Return first item in sequence where f(item) == True.""" - index = 0 - for item in seq: - if f(item): - return item, index - index += 1 - return None, -1 diff --git a/conductor/conductor/openstack/__init__.py b/conductor/conductor/openstack/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/conductor/conductor/openstack/common/__init__.py b/conductor/conductor/openstack/common/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/conductor/conductor/openstack/common/eventlet_backdoor.py b/conductor/conductor/openstack/common/eventlet_backdoor.py deleted file mode 100644 index c0ad460f..00000000 --- a/conductor/conductor/openstack/common/eventlet_backdoor.py +++ /dev/null @@ -1,87 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright (c) 2012 OpenStack Foundation. -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import gc -import pprint -import sys -import traceback - -import eventlet -import eventlet.backdoor -import greenlet -from oslo.config import cfg - -eventlet_backdoor_opts = [ - cfg.IntOpt('backdoor_port', - default=None, - help='port for eventlet backdoor to listen') -] - -CONF = cfg.CONF -CONF.register_opts(eventlet_backdoor_opts) - - -def _dont_use_this(): - print "Don't use this, just disconnect instead" - - -def _find_objects(t): - return filter(lambda o: isinstance(o, t), gc.get_objects()) - - -def _print_greenthreads(): - for i, gt in enumerate(_find_objects(greenlet.greenlet)): - print i, gt - traceback.print_stack(gt.gr_frame) - print - - -def _print_nativethreads(): - for threadId, stack in sys._current_frames().items(): - print threadId - traceback.print_stack(stack) - print - - -def initialize_if_enabled(): - backdoor_locals = { - 'exit': _dont_use_this, # So we don't exit the entire process - 'quit': _dont_use_this, # So we don't exit the entire process - 'fo': _find_objects, - 'pgt': _print_greenthreads, - 'pnt': _print_nativethreads, - } - - if CONF.backdoor_port is None: - return None - - # NOTE(johannes): The standard sys.displayhook will print the value of - # the last expression and set it to __builtin__._, which overwrites - # the __builtin__._ that gettext sets. Let's switch to using pprint - # since it won't interact poorly with gettext, and it's easier to - # read the output too. - def displayhook(val): - if val is not None: - pprint.pprint(val) - sys.displayhook = displayhook - - sock = eventlet.listen(('localhost', CONF.backdoor_port)) - port = sock.getsockname()[1] - eventlet.spawn_n(eventlet.backdoor.backdoor_server, sock, - locals=backdoor_locals) - return port diff --git a/conductor/conductor/openstack/common/exception.py b/conductor/conductor/openstack/common/exception.py deleted file mode 100644 index 5890c582..00000000 --- a/conductor/conductor/openstack/common/exception.py +++ /dev/null @@ -1,142 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Exceptions common to OpenStack projects -""" - -import logging - -from conductor.openstack.common.gettextutils import _ - -_FATAL_EXCEPTION_FORMAT_ERRORS = False - - -class Error(Exception): - def __init__(self, message=None): - super(Error, self).__init__(message) - - -class ApiError(Error): - def __init__(self, message='Unknown', code='Unknown'): - self.message = message - self.code = code - super(ApiError, self).__init__('%s: %s' % (code, message)) - - -class NotFound(Error): - pass - - -class UnknownScheme(Error): - - msg = "Unknown scheme '%s' found in URI" - - def __init__(self, scheme): - msg = self.__class__.msg % scheme - super(UnknownScheme, self).__init__(msg) - - -class BadStoreUri(Error): - - msg = "The Store URI %s was malformed. Reason: %s" - - def __init__(self, uri, reason): - msg = self.__class__.msg % (uri, reason) - super(BadStoreUri, self).__init__(msg) - - -class Duplicate(Error): - pass - - -class NotAuthorized(Error): - pass - - -class NotEmpty(Error): - pass - - -class Invalid(Error): - pass - - -class BadInputError(Exception): - """Error resulting from a client sending bad input to a server""" - pass - - -class MissingArgumentError(Error): - pass - - -class DatabaseMigrationError(Error): - pass - - -class ClientConnectionError(Exception): - """Error resulting from a client connecting to a server""" - pass - - -def wrap_exception(f): - def _wrap(*args, **kw): - try: - return f(*args, **kw) - except Exception, e: - if not isinstance(e, Error): - #exc_type, exc_value, exc_traceback = sys.exc_info() - logging.exception(_('Uncaught exception')) - #logging.error(traceback.extract_stack(exc_traceback)) - raise Error(str(e)) - raise - _wrap.func_name = f.func_name - return _wrap - - -class OpenstackException(Exception): - """ - Base Exception - - To correctly use this class, inherit from it and define - a 'message' property. That message will get printf'd - with the keyword arguments provided to the constructor. - """ - message = "An unknown exception occurred" - - def __init__(self, **kwargs): - try: - self._error_string = self.message % kwargs - - except Exception as e: - if _FATAL_EXCEPTION_FORMAT_ERRORS: - raise e - else: - # at least get the core message out if something happened - self._error_string = self.message - - def __str__(self): - return self._error_string - - -class MalformedRequestBody(OpenstackException): - message = "Malformed message body: %(reason)s" - - -class InvalidContentType(OpenstackException): - message = "Invalid content type %(content_type)s" diff --git a/conductor/conductor/openstack/common/gettextutils.py b/conductor/conductor/openstack/common/gettextutils.py deleted file mode 100644 index 3a81206c..00000000 --- a/conductor/conductor/openstack/common/gettextutils.py +++ /dev/null @@ -1,33 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -gettext for openstack-common modules. - -Usual usage in an openstack.common module: - - from conductor.openstack.common.gettextutils import _ -""" - -import gettext - - -t = gettext.translation('conductor', 'locale', fallback=True) - - -def _(msg): - return t.ugettext(msg) diff --git a/conductor/conductor/openstack/common/importutils.py b/conductor/conductor/openstack/common/importutils.py deleted file mode 100644 index 3bd277f4..00000000 --- a/conductor/conductor/openstack/common/importutils.py +++ /dev/null @@ -1,67 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Import related utilities and helper functions. -""" - -import sys -import traceback - - -def import_class(import_str): - """Returns a class from a string including module and class""" - mod_str, _sep, class_str = import_str.rpartition('.') - try: - __import__(mod_str) - return getattr(sys.modules[mod_str], class_str) - except (ValueError, AttributeError): - raise ImportError('Class %s cannot be found (%s)' % - (class_str, - traceback.format_exception(*sys.exc_info()))) - - -def import_object(import_str, *args, **kwargs): - """Import a class and return an instance of it.""" - return import_class(import_str)(*args, **kwargs) - - -def import_object_ns(name_space, import_str, *args, **kwargs): - """ - Import a class and return an instance of it, first by trying - to find the class in a default namespace, then failing back to - a full path if not found in the default namespace. - """ - import_value = "%s.%s" % (name_space, import_str) - try: - return import_class(import_value)(*args, **kwargs) - except ImportError: - return import_class(import_str)(*args, **kwargs) - - -def import_module(import_str): - """Import a module.""" - __import__(import_str) - return sys.modules[import_str] - - -def try_import(import_str, default=None): - """Try to import a module and if it fails return default.""" - try: - return import_module(import_str) - except ImportError: - return default diff --git a/conductor/conductor/openstack/common/jsonutils.py b/conductor/conductor/openstack/common/jsonutils.py deleted file mode 100644 index 4d3ddd05..00000000 --- a/conductor/conductor/openstack/common/jsonutils.py +++ /dev/null @@ -1,141 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# Copyright 2011 Justin Santa Barbara -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -''' -JSON related utilities. - -This module provides a few things: - - 1) A handy function for getting an object down to something that can be - JSON serialized. See to_primitive(). - - 2) Wrappers around loads() and dumps(). The dumps() wrapper will - automatically use to_primitive() for you if needed. - - 3) This sets up anyjson to use the loads() and dumps() wrappers if anyjson - is available. -''' - - -import datetime -import functools -import inspect -import itertools -import json -import xmlrpclib - -from conductor.openstack.common import timeutils - - -def to_primitive(value, convert_instances=False, convert_datetime=True, - level=0, max_depth=3): - """Convert a complex object into primitives. - - Handy for JSON serialization. We can optionally handle instances, - but since this is a recursive function, we could have cyclical - data structures. - - To handle cyclical data structures we could track the actual objects - visited in a set, but not all objects are hashable. Instead we just - track the depth of the object inspections and don't go too deep. - - Therefore, convert_instances=True is lossy ... be aware. - - """ - nasty = [inspect.ismodule, inspect.isclass, inspect.ismethod, - inspect.isfunction, inspect.isgeneratorfunction, - inspect.isgenerator, inspect.istraceback, inspect.isframe, - inspect.iscode, inspect.isbuiltin, inspect.isroutine, - inspect.isabstract] - for test in nasty: - if test(value): - return unicode(value) - - # value of itertools.count doesn't get caught by inspects - # above and results in infinite loop when list(value) is called. - if type(value) == itertools.count: - return unicode(value) - - # FIXME(vish): Workaround for LP bug 852095. Without this workaround, - # tests that raise an exception in a mocked method that - # has a @wrap_exception with a notifier will fail. If - # we up the dependency to 0.5.4 (when it is released) we - # can remove this workaround. - if getattr(value, '__module__', None) == 'mox': - return 'mock' - - if level > max_depth: - return '?' - - # The try block may not be necessary after the class check above, - # but just in case ... - try: - recursive = functools.partial(to_primitive, - convert_instances=convert_instances, - convert_datetime=convert_datetime, - level=level, - max_depth=max_depth) - # It's not clear why xmlrpclib created their own DateTime type, but - # for our purposes, make it a datetime type which is explicitly - # handled - if isinstance(value, xmlrpclib.DateTime): - value = datetime.datetime(*tuple(value.timetuple())[:6]) - - if isinstance(value, (list, tuple)): - return [recursive(v) for v in value] - elif isinstance(value, dict): - return dict((k, recursive(v)) for k, v in value.iteritems()) - elif convert_datetime and isinstance(value, datetime.datetime): - return timeutils.strtime(value) - elif hasattr(value, 'iteritems'): - return recursive(dict(value.iteritems()), level=level + 1) - elif hasattr(value, '__iter__'): - return recursive(list(value)) - elif convert_instances and hasattr(value, '__dict__'): - # Likely an instance of something. Watch for cycles. - # Ignore class member vars. - return recursive(value.__dict__, level=level + 1) - else: - return value - except TypeError: - # Class objects are tricky since they may define something like - # __iter__ defined but it isn't callable as list(). - return unicode(value) - - -def dumps(value, default=to_primitive, **kwargs): - return json.dumps(value, default=default, **kwargs) - - -def loads(s): - return json.loads(s) - - -def load(s): - return json.load(s) - - -try: - import anyjson -except ImportError: - pass -else: - anyjson._modules.append((__name__, 'dumps', TypeError, - 'loads', ValueError, 'load')) - anyjson.force_implementation(__name__) diff --git a/conductor/conductor/openstack/common/local.py b/conductor/conductor/openstack/common/local.py deleted file mode 100644 index f1bfc824..00000000 --- a/conductor/conductor/openstack/common/local.py +++ /dev/null @@ -1,48 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Greenthread local storage of variables using weak references""" - -import weakref - -from eventlet import corolocal - - -class WeakLocal(corolocal.local): - def __getattribute__(self, attr): - rval = corolocal.local.__getattribute__(self, attr) - if rval: - # NOTE(mikal): this bit is confusing. What is stored is a weak - # reference, not the value itself. We therefore need to lookup - # the weak reference and return the inner value here. - rval = rval() - return rval - - def __setattr__(self, attr, value): - value = weakref.ref(value) - return corolocal.local.__setattr__(self, attr, value) - - -# NOTE(mikal): the name "store" should be deprecated in the future -store = WeakLocal() - -# A "weak" store uses weak references and allows an object to fall out of scope -# when it falls out of scope in the code that uses the thread local storage. A -# "strong" store will hold a reference to the object so that it never falls out -# of scope. -weak_store = WeakLocal() -strong_store = corolocal.local diff --git a/conductor/conductor/openstack/common/log.py b/conductor/conductor/openstack/common/log.py deleted file mode 100644 index d8cd9fa0..00000000 --- a/conductor/conductor/openstack/common/log.py +++ /dev/null @@ -1,543 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack Foundation. -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Openstack logging handler. - -This module adds to logging functionality by adding the option to specify -a context object when calling the various log methods. If the context object -is not specified, default formatting is used. Additionally, an instance uuid -may be passed as part of the log message, which is intended to make it easier -for admins to find messages related to a specific instance. - -It also allows setting of formatting information through conf. - -""" - -import ConfigParser -import cStringIO -import inspect -import itertools -import logging -import logging.config -import logging.handlers -import os -import stat -import sys -import traceback - -from oslo.config import cfg - -from conductor.openstack.common.gettextutils import _ -from conductor.openstack.common import jsonutils -from conductor.openstack.common import local -from conductor.openstack.common import notifier - - -_DEFAULT_LOG_FORMAT = "%(asctime)s %(levelname)8s [%(name)s] %(message)s" -_DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S" - -common_cli_opts = [ - cfg.BoolOpt('debug', - short='d', - default=False, - help='Print debugging output (set logging level to ' - 'DEBUG instead of default WARNING level).'), - cfg.BoolOpt('verbose', - short='v', - default=False, - help='Print more verbose output (set logging level to ' - 'INFO instead of default WARNING level).'), -] - -logging_cli_opts = [ - cfg.StrOpt('log-config', - metavar='PATH', - help='If this option is specified, the logging configuration ' - 'file specified is used and overrides any other logging ' - 'options specified. Please see the Python logging module ' - 'documentation for details on logging configuration ' - 'files.'), - cfg.StrOpt('log-format', - default=_DEFAULT_LOG_FORMAT, - metavar='FORMAT', - help='A logging.Formatter log message format string which may ' - 'use any of the available logging.LogRecord attributes. ' - 'Default: %(default)s'), - cfg.StrOpt('log-date-format', - default=_DEFAULT_LOG_DATE_FORMAT, - metavar='DATE_FORMAT', - help='Format string for %%(asctime)s in log records. ' - 'Default: %(default)s'), - cfg.StrOpt('log-file', - metavar='PATH', - deprecated_name='logfile', - help='(Optional) Name of log file to output to. ' - 'If no default is set, logging will go to stdout.'), - cfg.StrOpt('log-dir', - deprecated_name='logdir', - help='(Optional) The base directory used for relative ' - '--log-file paths'), - cfg.BoolOpt('use-syslog', - default=False, - help='Use syslog for logging.'), - cfg.StrOpt('syslog-log-facility', - default='LOG_USER', - help='syslog facility to receive log lines') -] - -generic_log_opts = [ - cfg.BoolOpt('use_stderr', - default=True, - help='Log output to standard error'), - cfg.StrOpt('logfile_mode', - default='0644', - help='Default file mode used when creating log files'), -] - -log_opts = [ - cfg.StrOpt('logging_context_format_string', - default='%(asctime)s.%(msecs)03d %(levelname)s %(name)s ' - '[%(request_id)s %(user)s %(tenant)s] %(instance)s' - '%(message)s', - help='format string to use for log messages with context'), - cfg.StrOpt('logging_default_format_string', - default='%(asctime)s.%(msecs)03d %(process)d %(levelname)s ' - '%(name)s [-] %(instance)s%(message)s', - help='format string to use for log messages without context'), - cfg.StrOpt('logging_debug_format_suffix', - default='%(funcName)s %(pathname)s:%(lineno)d', - help='data to append to log format when level is DEBUG'), - cfg.StrOpt('logging_exception_prefix', - default='%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s ' - '%(instance)s', - help='prefix each line of exception output with this format'), - cfg.ListOpt('default_log_levels', - default=[ - 'amqplib=WARN', - 'sqlalchemy=WARN', - 'boto=WARN', - 'suds=INFO', - 'keystone=INFO', - 'eventlet.wsgi.server=WARN' - ], - help='list of logger=LEVEL pairs'), - cfg.BoolOpt('publish_errors', - default=False, - help='publish error events'), - cfg.BoolOpt('fatal_deprecations', - default=False, - help='make deprecations fatal'), - - # NOTE(mikal): there are two options here because sometimes we are handed - # a full instance (and could include more information), and other times we - # are just handed a UUID for the instance. - cfg.StrOpt('instance_format', - default='[instance: %(uuid)s] ', - help='If an instance is passed with the log message, format ' - 'it like this'), - cfg.StrOpt('instance_uuid_format', - default='[instance: %(uuid)s] ', - help='If an instance UUID is passed with the log message, ' - 'format it like this'), -] - -CONF = cfg.CONF -CONF.register_cli_opts(common_cli_opts) -CONF.register_cli_opts(logging_cli_opts) -CONF.register_opts(generic_log_opts) -CONF.register_opts(log_opts) - -# our new audit level -# NOTE(jkoelker) Since we synthesized an audit level, make the logging -# module aware of it so it acts like other levels. -logging.AUDIT = logging.INFO + 1 -logging.addLevelName(logging.AUDIT, 'AUDIT') - - -try: - NullHandler = logging.NullHandler -except AttributeError: # NOTE(jkoelker) NullHandler added in Python 2.7 - class NullHandler(logging.Handler): - def handle(self, record): - pass - - def emit(self, record): - pass - - def createLock(self): - self.lock = None - - -def _dictify_context(context): - if context is None: - return None - if not isinstance(context, dict) and getattr(context, 'to_dict', None): - context = context.to_dict() - return context - - -def _get_binary_name(): - return os.path.basename(inspect.stack()[-1][1]) - - -def _get_log_file_path(binary=None): - logfile = CONF.log_file - logdir = CONF.log_dir - - if logfile and not logdir: - return logfile - - if logfile and logdir: - return os.path.join(logdir, logfile) - - if logdir: - binary = binary or _get_binary_name() - return '%s.log' % (os.path.join(logdir, binary),) - - -class ContextAdapter(logging.LoggerAdapter): - warn = logging.LoggerAdapter.warning - - def __init__(self, logger, project_name, version_string): - self.logger = logger - self.project = project_name - self.version = version_string - - def audit(self, msg, *args, **kwargs): - self.log(logging.AUDIT, msg, *args, **kwargs) - - def deprecated(self, msg, *args, **kwargs): - stdmsg = _("Deprecated: %s") % msg - if CONF.fatal_deprecations: - self.critical(stdmsg, *args, **kwargs) - raise DeprecatedConfig(msg=stdmsg) - else: - self.warn(stdmsg, *args, **kwargs) - - def process(self, msg, kwargs): - if 'extra' not in kwargs: - kwargs['extra'] = {} - extra = kwargs['extra'] - - context = kwargs.pop('context', None) - if not context: - context = getattr(local.store, 'context', None) - if context: - extra.update(_dictify_context(context)) - - instance = kwargs.pop('instance', None) - instance_extra = '' - if instance: - instance_extra = CONF.instance_format % instance - else: - instance_uuid = kwargs.pop('instance_uuid', None) - if instance_uuid: - instance_extra = (CONF.instance_uuid_format - % {'uuid': instance_uuid}) - extra.update({'instance': instance_extra}) - - extra.update({"project": self.project}) - extra.update({"version": self.version}) - extra['extra'] = extra.copy() - return msg, kwargs - - -class JSONFormatter(logging.Formatter): - def __init__(self, fmt=None, datefmt=None): - # NOTE(jkoelker) we ignore the fmt argument, but its still there - # since logging.config.fileConfig passes it. - self.datefmt = datefmt - - def formatException(self, ei, strip_newlines=True): - lines = traceback.format_exception(*ei) - if strip_newlines: - lines = [itertools.ifilter( - lambda x: x, - line.rstrip().splitlines()) for line in lines] - lines = list(itertools.chain(*lines)) - return lines - - def format(self, record): - message = {'message': record.getMessage(), - 'asctime': self.formatTime(record, self.datefmt), - 'name': record.name, - 'msg': record.msg, - 'args': record.args, - 'levelname': record.levelname, - 'levelno': record.levelno, - 'pathname': record.pathname, - 'filename': record.filename, - 'module': record.module, - 'lineno': record.lineno, - 'funcname': record.funcName, - 'created': record.created, - 'msecs': record.msecs, - 'relative_created': record.relativeCreated, - 'thread': record.thread, - 'thread_name': record.threadName, - 'process_name': record.processName, - 'process': record.process, - 'traceback': None} - - if hasattr(record, 'extra'): - message['extra'] = record.extra - - if record.exc_info: - message['traceback'] = self.formatException(record.exc_info) - - return jsonutils.dumps(message) - - -class PublishErrorsHandler(logging.Handler): - def emit(self, record): - if ('conductor.openstack.common.notifier.log_notifier' in - CONF.notification_driver): - return - notifier.api.notify(None, 'error.publisher', - 'error_notification', - notifier.api.ERROR, - dict(error=record.msg)) - - -def _create_logging_excepthook(product_name): - def logging_excepthook(type, value, tb): - extra = {} - if CONF.verbose: - extra['exc_info'] = (type, value, tb) - getLogger(product_name).critical(str(value), **extra) - return logging_excepthook - - -class LogConfigError(Exception): - - message = _('Error loading logging config %(log_config)s: %(err_msg)s') - - def __init__(self, log_config, err_msg): - self.log_config = log_config - self.err_msg = err_msg - - def __str__(self): - return self.message % dict(log_config=self.log_config, - err_msg=self.err_msg) - - -def _load_log_config(log_config): - try: - logging.config.fileConfig(log_config) - except ConfigParser.Error, exc: - raise LogConfigError(log_config, str(exc)) - - -def setup(product_name): - """Setup logging.""" - if CONF.log_config: - _load_log_config(CONF.log_config) - else: - _setup_logging_from_conf() - sys.excepthook = _create_logging_excepthook(product_name) - - -def set_defaults(logging_context_format_string): - cfg.set_defaults(log_opts, - logging_context_format_string= - logging_context_format_string) - - -def _find_facility_from_conf(): - facility_names = logging.handlers.SysLogHandler.facility_names - facility = getattr(logging.handlers.SysLogHandler, - CONF.syslog_log_facility, - None) - - if facility is None and CONF.syslog_log_facility in facility_names: - facility = facility_names.get(CONF.syslog_log_facility) - - if facility is None: - valid_facilities = facility_names.keys() - consts = ['LOG_AUTH', 'LOG_AUTHPRIV', 'LOG_CRON', 'LOG_DAEMON', - 'LOG_FTP', 'LOG_KERN', 'LOG_LPR', 'LOG_MAIL', 'LOG_NEWS', - 'LOG_AUTH', 'LOG_SYSLOG', 'LOG_USER', 'LOG_UUCP', - 'LOG_LOCAL0', 'LOG_LOCAL1', 'LOG_LOCAL2', 'LOG_LOCAL3', - 'LOG_LOCAL4', 'LOG_LOCAL5', 'LOG_LOCAL6', 'LOG_LOCAL7'] - valid_facilities.extend(consts) - raise TypeError(_('syslog facility must be one of: %s') % - ', '.join("'%s'" % fac - for fac in valid_facilities)) - - return facility - - -def _setup_logging_from_conf(): - log_root = getLogger(None).logger - for handler in log_root.handlers: - log_root.removeHandler(handler) - - if CONF.use_syslog: - facility = _find_facility_from_conf() - syslog = logging.handlers.SysLogHandler(address='/dev/log', - facility=facility) - log_root.addHandler(syslog) - - logpath = _get_log_file_path() - if logpath: - filelog = logging.handlers.WatchedFileHandler(logpath) - log_root.addHandler(filelog) - - mode = int(CONF.logfile_mode, 8) - st = os.stat(logpath) - if st.st_mode != (stat.S_IFREG | mode): - os.chmod(logpath, mode) - - if CONF.use_stderr: - streamlog = ColorHandler() - log_root.addHandler(streamlog) - - elif not CONF.log_file: - # pass sys.stdout as a positional argument - # python2.6 calls the argument strm, in 2.7 it's stream - streamlog = logging.StreamHandler(sys.stdout) - log_root.addHandler(streamlog) - - if CONF.publish_errors: - log_root.addHandler(PublishErrorsHandler(logging.ERROR)) - - for handler in log_root.handlers: - datefmt = CONF.log_date_format - if CONF.log_format: - handler.setFormatter(logging.Formatter(fmt=CONF.log_format, - datefmt=datefmt)) - else: - handler.setFormatter(LegacyFormatter(datefmt=datefmt)) - - if CONF.debug: - log_root.setLevel(logging.DEBUG) - elif CONF.verbose: - log_root.setLevel(logging.INFO) - else: - log_root.setLevel(logging.WARNING) - - level = logging.NOTSET - for pair in CONF.default_log_levels: - mod, _sep, level_name = pair.partition('=') - level = logging.getLevelName(level_name) - logger = logging.getLogger(mod) - logger.setLevel(level) - for handler in log_root.handlers: - logger.addHandler(handler) - -_loggers = {} - - -def getLogger(name='unknown', version='unknown'): - if name not in _loggers: - _loggers[name] = ContextAdapter(logging.getLogger(name), - name, - version) - return _loggers[name] - - -class WritableLogger(object): - """A thin wrapper that responds to `write` and logs.""" - - def __init__(self, logger, level=logging.INFO): - self.logger = logger - self.level = level - - def write(self, msg): - self.logger.log(self.level, msg) - - -class LegacyFormatter(logging.Formatter): - """A context.RequestContext aware formatter configured through flags. - - The flags used to set format strings are: logging_context_format_string - and logging_default_format_string. You can also specify - logging_debug_format_suffix to append extra formatting if the log level is - debug. - - For information about what variables are available for the formatter see: - http://docs.python.org/library/logging.html#formatter - - """ - - def format(self, record): - """Uses contextstring if request_id is set, otherwise default.""" - # NOTE(sdague): default the fancier formating params - # to an empty string so we don't throw an exception if - # they get used - for key in ('instance', 'color'): - if key not in record.__dict__: - record.__dict__[key] = '' - - if record.__dict__.get('request_id', None): - self._fmt = CONF.logging_context_format_string - else: - self._fmt = CONF.logging_default_format_string - - if (record.levelno == logging.DEBUG and - CONF.logging_debug_format_suffix): - self._fmt += " " + CONF.logging_debug_format_suffix - - # Cache this on the record, Logger will respect our formated copy - if record.exc_info: - record.exc_text = self.formatException(record.exc_info, record) - return logging.Formatter.format(self, record) - - def formatException(self, exc_info, record=None): - """Format exception output with CONF.logging_exception_prefix.""" - if not record: - return logging.Formatter.formatException(self, exc_info) - - stringbuffer = cStringIO.StringIO() - traceback.print_exception(exc_info[0], exc_info[1], exc_info[2], - None, stringbuffer) - lines = stringbuffer.getvalue().split('\n') - stringbuffer.close() - - if CONF.logging_exception_prefix.find('%(asctime)') != -1: - record.asctime = self.formatTime(record, self.datefmt) - - formatted_lines = [] - for line in lines: - pl = CONF.logging_exception_prefix % record.__dict__ - fl = '%s%s' % (pl, line) - formatted_lines.append(fl) - return '\n'.join(formatted_lines) - - -class ColorHandler(logging.StreamHandler): - LEVEL_COLORS = { - logging.DEBUG: '\033[00;32m', # GREEN - logging.INFO: '\033[00;36m', # CYAN - logging.AUDIT: '\033[01;36m', # BOLD CYAN - logging.WARN: '\033[01;33m', # BOLD YELLOW - logging.ERROR: '\033[01;31m', # BOLD RED - logging.CRITICAL: '\033[01;31m', # BOLD RED - } - - def format(self, record): - record.color = self.LEVEL_COLORS[record.levelno] - return logging.StreamHandler.format(self, record) - - -class DeprecatedConfig(Exception): - message = _("Fatal call to deprecated config: %(msg)s") - - def __init__(self, msg): - super(Exception, self).__init__(self.message % dict(msg=msg)) diff --git a/conductor/conductor/openstack/common/loopingcall.py b/conductor/conductor/openstack/common/loopingcall.py deleted file mode 100644 index 08135f67..00000000 --- a/conductor/conductor/openstack/common/loopingcall.py +++ /dev/null @@ -1,95 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# Copyright 2011 Justin Santa Barbara -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import sys - -from eventlet import event -from eventlet import greenthread - -from conductor.openstack.common.gettextutils import _ -from conductor.openstack.common import log as logging -from conductor.openstack.common import timeutils - -LOG = logging.getLogger(__name__) - - -class LoopingCallDone(Exception): - """Exception to break out and stop a LoopingCall. - - The poll-function passed to LoopingCall can raise this exception to - break out of the loop normally. This is somewhat analogous to - StopIteration. - - An optional return-value can be included as the argument to the exception; - this return-value will be returned by LoopingCall.wait() - - """ - - def __init__(self, retvalue=True): - """:param retvalue: Value that LoopingCall.wait() should return.""" - self.retvalue = retvalue - - -class LoopingCall(object): - def __init__(self, f=None, *args, **kw): - self.args = args - self.kw = kw - self.f = f - self._running = False - - def start(self, interval, initial_delay=None): - self._running = True - done = event.Event() - - def _inner(): - if initial_delay: - greenthread.sleep(initial_delay) - - try: - while self._running: - start = timeutils.utcnow() - self.f(*self.args, **self.kw) - end = timeutils.utcnow() - if not self._running: - break - delay = interval - timeutils.delta_seconds(start, end) - if delay <= 0: - LOG.warn(_('task run outlasted interval by %s sec') % - -delay) - greenthread.sleep(delay if delay > 0 else 0) - except LoopingCallDone, e: - self.stop() - done.send(e.retvalue) - except Exception: - LOG.exception(_('in looping call')) - done.send_exception(*sys.exc_info()) - return - else: - done.send(True) - - self.done = done - - greenthread.spawn_n(_inner) - return self.done - - def stop(self): - self._running = False - - def wait(self): - return self.done.wait() diff --git a/conductor/conductor/openstack/common/notifier/__init__.py b/conductor/conductor/openstack/common/notifier/__init__.py deleted file mode 100644 index 45c3b46a..00000000 --- a/conductor/conductor/openstack/common/notifier/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. diff --git a/conductor/conductor/openstack/common/notifier/api.py b/conductor/conductor/openstack/common/notifier/api.py deleted file mode 100644 index d5629e81..00000000 --- a/conductor/conductor/openstack/common/notifier/api.py +++ /dev/null @@ -1,182 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from oslo.config import cfg - -from conductor.openstack.common import context -from conductor.openstack.common.gettextutils import _ -from conductor.openstack.common import importutils -from conductor.openstack.common import jsonutils -from conductor.openstack.common import log as logging -from conductor.openstack.common import timeutils - - -LOG = logging.getLogger(__name__) - -notifier_opts = [ - cfg.MultiStrOpt('notification_driver', - default=[], - help='Driver or drivers to handle sending notifications'), - cfg.StrOpt('default_notification_level', - default='INFO', - help='Default notification level for outgoing notifications'), - cfg.StrOpt('default_publisher_id', - default='$host', - help='Default publisher_id for outgoing notifications'), -] - -CONF = cfg.CONF -CONF.register_opts(notifier_opts) - -WARN = 'WARN' -INFO = 'INFO' -ERROR = 'ERROR' -CRITICAL = 'CRITICAL' -DEBUG = 'DEBUG' - -log_levels = (DEBUG, WARN, INFO, ERROR, CRITICAL) - - -class BadPriorityException(Exception): - pass - - -def notify_decorator(name, fn): - """ decorator for notify which is used from utils.monkey_patch() - - :param name: name of the function - :param function: - object of the function - :returns: function -- decorated function - - """ - def wrapped_func(*args, **kwarg): - body = {} - body['args'] = [] - body['kwarg'] = {} - for arg in args: - body['args'].append(arg) - for key in kwarg: - body['kwarg'][key] = kwarg[key] - - ctxt = context.get_context_from_function_and_args(fn, args, kwarg) - notify(ctxt, - CONF.default_publisher_id, - name, - CONF.default_notification_level, - body) - return fn(*args, **kwarg) - return wrapped_func - - -def publisher_id(service, host=None): - if not host: - host = CONF.host - return "%s.%s" % (service, host) - - -def notify(context, publisher_id, event_type, priority, payload): - """Sends a notification using the specified driver - - :param publisher_id: the source worker_type.host of the message - :param event_type: the literal type of event (ex. Instance Creation) - :param priority: patterned after the enumeration of Python logging - levels in the set (DEBUG, WARN, INFO, ERROR, CRITICAL) - :param payload: A python dictionary of attributes - - Outgoing message format includes the above parameters, and appends the - following: - - message_id - a UUID representing the id for this notification - - timestamp - the GMT timestamp the notification was sent at - - The composite message will be constructed as a dictionary of the above - attributes, which will then be sent via the transport mechanism defined - by the driver. - - Message example:: - - {'message_id': str(uuid.uuid4()), - 'publisher_id': 'compute.host1', - 'timestamp': timeutils.utcnow(), - 'priority': 'WARN', - 'event_type': 'compute.create_instance', - 'payload': {'instance_id': 12, ... }} - - """ - if priority not in log_levels: - raise BadPriorityException( - _('%s not in valid priorities') % priority) - - # Ensure everything is JSON serializable. - payload = jsonutils.to_primitive(payload, convert_instances=True) - - msg = dict(message_id=str(uuid.uuid4()), - publisher_id=publisher_id, - event_type=event_type, - priority=priority, - payload=payload, - timestamp=str(timeutils.utcnow())) - - for driver in _get_drivers(): - try: - driver.notify(context, msg) - except Exception as e: - LOG.exception(_("Problem '%(e)s' attempting to " - "send to notification system. " - "Payload=%(payload)s") - % dict(e=e, payload=payload)) - - -_drivers = None - - -def _get_drivers(): - """Instantiate, cache, and return drivers based on the CONF.""" - global _drivers - if _drivers is None: - _drivers = {} - for notification_driver in CONF.notification_driver: - add_driver(notification_driver) - - return _drivers.values() - - -def add_driver(notification_driver): - """Add a notification driver at runtime.""" - # Make sure the driver list is initialized. - _get_drivers() - if isinstance(notification_driver, basestring): - # Load and add - try: - driver = importutils.import_module(notification_driver) - _drivers[notification_driver] = driver - except ImportError: - LOG.exception(_("Failed to load notifier %s. " - "These notifications will not be sent.") % - notification_driver) - else: - # Driver is already loaded; just add the object. - _drivers[notification_driver] = notification_driver - - -def _reset_drivers(): - """Used by unit tests to reset the drivers.""" - global _drivers - _drivers = None diff --git a/conductor/conductor/openstack/common/notifier/log_notifier.py b/conductor/conductor/openstack/common/notifier/log_notifier.py deleted file mode 100644 index 9f159fa1..00000000 --- a/conductor/conductor/openstack/common/notifier/log_notifier.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo.config import cfg - -from conductor.openstack.common import jsonutils -from conductor.openstack.common import log as logging - - -CONF = cfg.CONF - - -def notify(_context, message): - """Notifies the recipient of the desired event given the model. - Log notifications using openstack's default logging system""" - - priority = message.get('priority', - CONF.default_notification_level) - priority = priority.lower() - logger = logging.getLogger( - 'conductor.openstack.common.notification.%s' % - message['event_type']) - getattr(logger, priority)(jsonutils.dumps(message)) diff --git a/conductor/conductor/openstack/common/notifier/no_op_notifier.py b/conductor/conductor/openstack/common/notifier/no_op_notifier.py deleted file mode 100644 index bc7a56ca..00000000 --- a/conductor/conductor/openstack/common/notifier/no_op_notifier.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -def notify(_context, message): - """Notifies the recipient of the desired event given the model""" - pass diff --git a/conductor/conductor/openstack/common/notifier/rpc_notifier.py b/conductor/conductor/openstack/common/notifier/rpc_notifier.py deleted file mode 100644 index 67d615d0..00000000 --- a/conductor/conductor/openstack/common/notifier/rpc_notifier.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo.config import cfg - -from conductor.openstack.common import context as req_context -from conductor.openstack.common.gettextutils import _ -from conductor.openstack.common import log as logging -from conductor.openstack.common import rpc - -LOG = logging.getLogger(__name__) - -notification_topic_opt = cfg.ListOpt( - 'notification_topics', default=['notifications', ], - help='AMQP topic used for openstack notifications') - -CONF = cfg.CONF -CONF.register_opt(notification_topic_opt) - - -def notify(context, message): - """Sends a notification via RPC""" - if not context: - context = req_context.get_admin_context() - priority = message.get('priority', - CONF.default_notification_level) - priority = priority.lower() - for topic in CONF.notification_topics: - topic = '%s.%s' % (topic, priority) - try: - rpc.notify(context, topic, message) - except Exception: - LOG.exception(_("Could not send notification to %(topic)s. " - "Payload=%(message)s"), locals()) diff --git a/conductor/conductor/openstack/common/notifier/rpc_notifier2.py b/conductor/conductor/openstack/common/notifier/rpc_notifier2.py deleted file mode 100644 index 3585e7e4..00000000 --- a/conductor/conductor/openstack/common/notifier/rpc_notifier2.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -'''messaging based notification driver, with message envelopes''' - -from oslo.config import cfg - -from conductor.openstack.common import context as req_context -from conductor.openstack.common.gettextutils import _ -from conductor.openstack.common import log as logging -from conductor.openstack.common import rpc - -LOG = logging.getLogger(__name__) - -notification_topic_opt = cfg.ListOpt( - 'topics', default=['notifications', ], - help='AMQP topic(s) used for openstack notifications') - -opt_group = cfg.OptGroup(name='rpc_notifier2', - title='Options for rpc_notifier2') - -CONF = cfg.CONF -CONF.register_group(opt_group) -CONF.register_opt(notification_topic_opt, opt_group) - - -def notify(context, message): - """Sends a notification via RPC""" - if not context: - context = req_context.get_admin_context() - priority = message.get('priority', - CONF.default_notification_level) - priority = priority.lower() - for topic in CONF.rpc_notifier2.topics: - topic = '%s.%s' % (topic, priority) - try: - rpc.notify(context, topic, message, envelope=True) - except Exception: - LOG.exception(_("Could not send notification to %(topic)s. " - "Payload=%(message)s"), locals()) diff --git a/conductor/conductor/openstack/common/notifier/test_notifier.py b/conductor/conductor/openstack/common/notifier/test_notifier.py deleted file mode 100644 index 96c1746b..00000000 --- a/conductor/conductor/openstack/common/notifier/test_notifier.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -NOTIFICATIONS = [] - - -def notify(_context, message): - """Test notifier, stores notifications in memory for unittests.""" - NOTIFICATIONS.append(message) diff --git a/conductor/conductor/openstack/common/service.py b/conductor/conductor/openstack/common/service.py deleted file mode 100644 index a31b41a8..00000000 --- a/conductor/conductor/openstack/common/service.py +++ /dev/null @@ -1,332 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# Copyright 2011 Justin Santa Barbara -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Generic Node base class for all workers that run on hosts.""" - -import errno -import os -import random -import signal -import sys -import time - -import eventlet -import logging as std_logging -from oslo.config import cfg - -from conductor.openstack.common import eventlet_backdoor -from conductor.openstack.common.gettextutils import _ -from conductor.openstack.common import importutils -from conductor.openstack.common import log as logging -from conductor.openstack.common import threadgroup - - -rpc = importutils.try_import('conductor.openstack.common.rpc') -CONF = cfg.CONF -LOG = logging.getLogger(__name__) - - -class Launcher(object): - """Launch one or more services and wait for them to complete.""" - - def __init__(self): - """Initialize the service launcher. - - :returns: None - - """ - self._services = threadgroup.ThreadGroup() - eventlet_backdoor.initialize_if_enabled() - - @staticmethod - def run_service(service): - """Start and wait for a service to finish. - - :param service: service to run and wait for. - :returns: None - - """ - service.start() - service.wait() - - def launch_service(self, service): - """Load and start the given service. - - :param service: The service you would like to start. - :returns: None - - """ - self._services.add_thread(self.run_service, service) - - def stop(self): - """Stop all services which are currently running. - - :returns: None - - """ - self._services.stop() - - def wait(self): - """Waits until all services have been stopped, and then returns. - - :returns: None - - """ - self._services.wait() - - -class SignalExit(SystemExit): - def __init__(self, signo, exccode=1): - super(SignalExit, self).__init__(exccode) - self.signo = signo - - -class ServiceLauncher(Launcher): - def _handle_signal(self, signo, frame): - # Allow the process to be killed again and die from natural causes - signal.signal(signal.SIGTERM, signal.SIG_DFL) - signal.signal(signal.SIGINT, signal.SIG_DFL) - - raise SignalExit(signo) - - def wait(self): - signal.signal(signal.SIGTERM, self._handle_signal) - signal.signal(signal.SIGINT, self._handle_signal) - - LOG.debug(_('Full set of CONF:')) - CONF.log_opt_values(LOG, std_logging.DEBUG) - - status = None - try: - super(ServiceLauncher, self).wait() - except SignalExit as exc: - signame = {signal.SIGTERM: 'SIGTERM', - signal.SIGINT: 'SIGINT'}[exc.signo] - LOG.info(_('Caught %s, exiting'), signame) - status = exc.code - except SystemExit as exc: - status = exc.code - finally: - if rpc: - rpc.cleanup() - self.stop() - return status - - -class ServiceWrapper(object): - def __init__(self, service, workers): - self.service = service - self.workers = workers - self.children = set() - self.forktimes = [] - - -class ProcessLauncher(object): - def __init__(self): - self.children = {} - self.sigcaught = None - self.running = True - rfd, self.writepipe = os.pipe() - self.readpipe = eventlet.greenio.GreenPipe(rfd, 'r') - - signal.signal(signal.SIGTERM, self._handle_signal) - signal.signal(signal.SIGINT, self._handle_signal) - - def _handle_signal(self, signo, frame): - self.sigcaught = signo - self.running = False - - # Allow the process to be killed again and die from natural causes - signal.signal(signal.SIGTERM, signal.SIG_DFL) - signal.signal(signal.SIGINT, signal.SIG_DFL) - - def _pipe_watcher(self): - # This will block until the write end is closed when the parent - # dies unexpectedly - self.readpipe.read() - - LOG.info(_('Parent process has died unexpectedly, exiting')) - - sys.exit(1) - - def _child_process(self, service): - # Setup child signal handlers differently - def _sigterm(*args): - signal.signal(signal.SIGTERM, signal.SIG_DFL) - raise SignalExit(signal.SIGTERM) - - signal.signal(signal.SIGTERM, _sigterm) - # Block SIGINT and let the parent send us a SIGTERM - signal.signal(signal.SIGINT, signal.SIG_IGN) - - # Reopen the eventlet hub to make sure we don't share an epoll - # fd with parent and/or siblings, which would be bad - eventlet.hubs.use_hub() - - # Close write to ensure only parent has it open - os.close(self.writepipe) - # Create greenthread to watch for parent to close pipe - eventlet.spawn_n(self._pipe_watcher) - - # Reseed random number generator - random.seed() - - launcher = Launcher() - launcher.run_service(service) - - def _start_child(self, wrap): - if len(wrap.forktimes) > wrap.workers: - # Limit ourselves to one process a second (over the period of - # number of workers * 1 second). This will allow workers to - # start up quickly but ensure we don't fork off children that - # die instantly too quickly. - if time.time() - wrap.forktimes[0] < wrap.workers: - LOG.info(_('Forking too fast, sleeping')) - time.sleep(1) - - wrap.forktimes.pop(0) - - wrap.forktimes.append(time.time()) - - pid = os.fork() - if pid == 0: - # NOTE(johannes): All exceptions are caught to ensure this - # doesn't fallback into the loop spawning children. It would - # be bad for a child to spawn more children. - status = 0 - try: - self._child_process(wrap.service) - except SignalExit as exc: - signame = {signal.SIGTERM: 'SIGTERM', - signal.SIGINT: 'SIGINT'}[exc.signo] - LOG.info(_('Caught %s, exiting'), signame) - status = exc.code - except SystemExit as exc: - status = exc.code - except BaseException: - LOG.exception(_('Unhandled exception')) - status = 2 - finally: - wrap.service.stop() - - os._exit(status) - - LOG.info(_('Started child %d'), pid) - - wrap.children.add(pid) - self.children[pid] = wrap - - return pid - - def launch_service(self, service, workers=1): - wrap = ServiceWrapper(service, workers) - - LOG.info(_('Starting %d workers'), wrap.workers) - while self.running and len(wrap.children) < wrap.workers: - self._start_child(wrap) - - def _wait_child(self): - try: - # Don't block if no child processes have exited - pid, status = os.waitpid(0, os.WNOHANG) - if not pid: - return None - except OSError as exc: - if exc.errno not in (errno.EINTR, errno.ECHILD): - raise - return None - - if os.WIFSIGNALED(status): - sig = os.WTERMSIG(status) - LOG.info(_('Child %(pid)d killed by signal %(sig)d'), - dict(pid=pid, sig=sig)) - else: - code = os.WEXITSTATUS(status) - LOG.info(_('Child %(pid)s exited with status %(code)d'), - dict(pid=pid, code=code)) - - if pid not in self.children: - LOG.warning(_('pid %d not in child list'), pid) - return None - - wrap = self.children.pop(pid) - wrap.children.remove(pid) - return wrap - - def wait(self): - """Loop waiting on children to die and respawning as necessary""" - - LOG.debug(_('Full set of CONF:')) - CONF.log_opt_values(LOG, std_logging.DEBUG) - - while self.running: - wrap = self._wait_child() - if not wrap: - # Yield to other threads if no children have exited - # Sleep for a short time to avoid excessive CPU usage - # (see bug #1095346) - eventlet.greenthread.sleep(.01) - continue - - while self.running and len(wrap.children) < wrap.workers: - self._start_child(wrap) - - if self.sigcaught: - signame = {signal.SIGTERM: 'SIGTERM', - signal.SIGINT: 'SIGINT'}[self.sigcaught] - LOG.info(_('Caught %s, stopping children'), signame) - - for pid in self.children: - try: - os.kill(pid, signal.SIGTERM) - except OSError as exc: - if exc.errno != errno.ESRCH: - raise - - # Wait for children to die - if self.children: - LOG.info(_('Waiting on %d children to exit'), len(self.children)) - while self.children: - self._wait_child() - - -class Service(object): - """Service object for binaries running on hosts.""" - - def __init__(self, threads=1000): - self.tg = threadgroup.ThreadGroup(threads) - - def start(self): - pass - - def stop(self): - self.tg.stop() - - def wait(self): - self.tg.wait() - - -def launch(service, workers=None): - if workers: - launcher = ProcessLauncher() - launcher.launch_service(service, workers=workers) - else: - launcher = ServiceLauncher() - launcher.launch_service(service) - return launcher diff --git a/conductor/conductor/openstack/common/setup.py b/conductor/conductor/openstack/common/setup.py deleted file mode 100644 index dec74fd0..00000000 --- a/conductor/conductor/openstack/common/setup.py +++ /dev/null @@ -1,367 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack Foundation. -# Copyright 2012-2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Utilities with minimum-depends for use in setup.py -""" - -import email -import os -import re -import subprocess -import sys - -from setuptools.command import sdist - - -def parse_mailmap(mailmap='.mailmap'): - mapping = {} - if os.path.exists(mailmap): - with open(mailmap, 'r') as fp: - for l in fp: - try: - canonical_email, alias = re.match( - r'[^#]*?(<.+>).*(<.+>).*', l).groups() - except AttributeError: - continue - mapping[alias] = canonical_email - return mapping - - -def _parse_git_mailmap(git_dir, mailmap='.mailmap'): - mailmap = os.path.join(os.path.dirname(git_dir), mailmap) - return parse_mailmap(mailmap) - - -def canonicalize_emails(changelog, mapping): - """Takes in a string and an email alias mapping and replaces all - instances of the aliases in the string with their real email. - """ - for alias, email_address in mapping.iteritems(): - changelog = changelog.replace(alias, email_address) - return changelog - - -# Get requirements from the first file that exists -def get_reqs_from_files(requirements_files): - for requirements_file in requirements_files: - if os.path.exists(requirements_file): - with open(requirements_file, 'r') as fil: - return fil.read().split('\n') - return [] - - -def parse_requirements(requirements_files=['requirements.txt', - 'tools/pip-requires']): - requirements = [] - for line in get_reqs_from_files(requirements_files): - # For the requirements list, we need to inject only the portion - # after egg= so that distutils knows the package it's looking for - # such as: - # -e git://github.com/openstack/nova/master#egg=nova - if re.match(r'\s*-e\s+', line): - requirements.append(re.sub(r'\s*-e\s+.*#egg=(.*)$', r'\1', - line)) - # such as: - # http://github.com/openstack/nova/zipball/master#egg=nova - elif re.match(r'\s*https?:', line): - requirements.append(re.sub(r'\s*https?:.*#egg=(.*)$', r'\1', - line)) - # -f lines are for index locations, and don't get used here - elif re.match(r'\s*-f\s+', line): - pass - # argparse is part of the standard library starting with 2.7 - # adding it to the requirements list screws distro installs - elif line == 'argparse' and sys.version_info >= (2, 7): - pass - else: - requirements.append(line) - - return requirements - - -def parse_dependency_links(requirements_files=['requirements.txt', - 'tools/pip-requires']): - dependency_links = [] - # dependency_links inject alternate locations to find packages listed - # in requirements - for line in get_reqs_from_files(requirements_files): - # skip comments and blank lines - if re.match(r'(\s*#)|(\s*$)', line): - continue - # lines with -e or -f need the whole line, minus the flag - if re.match(r'\s*-[ef]\s+', line): - dependency_links.append(re.sub(r'\s*-[ef]\s+', '', line)) - # lines that are only urls can go in unmolested - elif re.match(r'\s*https?:', line): - dependency_links.append(line) - return dependency_links - - -def _run_shell_command(cmd, throw_on_error=False): - if os.name == 'nt': - output = subprocess.Popen(["cmd.exe", "/C", cmd], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - else: - output = subprocess.Popen(["/bin/sh", "-c", cmd], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - out = output.communicate() - if output.returncode and throw_on_error: - raise Exception("%s returned %d" % cmd, output.returncode) - if len(out) == 0: - return None - if len(out[0].strip()) == 0: - return None - return out[0].strip() - - -def _get_git_directory(): - parent_dir = os.path.dirname(__file__) - while True: - git_dir = os.path.join(parent_dir, '.git') - if os.path.exists(git_dir): - return git_dir - parent_dir, child = os.path.split(parent_dir) - if not child: # reached to root dir - return None - - -def write_git_changelog(): - """Write a changelog based on the git changelog.""" - new_changelog = 'ChangeLog' - git_dir = _get_git_directory() - if not os.getenv('SKIP_WRITE_GIT_CHANGELOG'): - if git_dir: - git_log_cmd = 'git --git-dir=%s log' % git_dir - changelog = _run_shell_command(git_log_cmd) - mailmap = _parse_git_mailmap(git_dir) - with open(new_changelog, "w") as changelog_file: - changelog_file.write(canonicalize_emails(changelog, mailmap)) - else: - open(new_changelog, 'w').close() - - -def generate_authors(): - """Create AUTHORS file using git commits.""" - jenkins_email = 'jenkins@review.(openstack|stackforge).org' - old_authors = 'AUTHORS.in' - new_authors = 'AUTHORS' - git_dir = _get_git_directory() - if not os.getenv('SKIP_GENERATE_AUTHORS'): - if git_dir: - # don't include jenkins email address in AUTHORS file - git_log_cmd = ("git --git-dir=" + git_dir + - " log --format='%aN <%aE>' | sort -u | " - "egrep -v '" + jenkins_email + "'") - changelog = _run_shell_command(git_log_cmd) - signed_cmd = ("git log --git-dir=" + git_dir + - " | grep -i Co-authored-by: | sort -u") - signed_entries = _run_shell_command(signed_cmd) - if signed_entries: - new_entries = "\n".join( - [signed.split(":", 1)[1].strip() - for signed in signed_entries.split("\n") if signed]) - changelog = "\n".join((changelog, new_entries)) - mailmap = _parse_git_mailmap(git_dir) - with open(new_authors, 'w') as new_authors_fh: - new_authors_fh.write(canonicalize_emails(changelog, mailmap)) - if os.path.exists(old_authors): - with open(old_authors, "r") as old_authors_fh: - new_authors_fh.write('\n' + old_authors_fh.read()) - else: - open(new_authors, 'w').close() - - -_rst_template = """%(heading)s -%(underline)s - -.. automodule:: %(module)s - :members: - :undoc-members: - :show-inheritance: -""" - - -def get_cmdclass(): - """Return dict of commands to run from setup.py.""" - - cmdclass = dict() - - def _find_modules(arg, dirname, files): - for filename in files: - if filename.endswith('.py') and filename != '__init__.py': - arg["%s.%s" % (dirname.replace('/', '.'), - filename[:-3])] = True - - class LocalSDist(sdist.sdist): - """Builds the ChangeLog and Authors files from VC first.""" - - def run(self): - write_git_changelog() - generate_authors() - # sdist.sdist is an old style class, can't use super() - sdist.sdist.run(self) - - cmdclass['sdist'] = LocalSDist - - # If Sphinx is installed on the box running setup.py, - # enable setup.py to build the documentation, otherwise, - # just ignore it - try: - from sphinx.setup_command import BuildDoc - - class LocalBuildDoc(BuildDoc): - - builders = ['html', 'man'] - - def generate_autoindex(self): - print "**Autodocumenting from %s" % os.path.abspath(os.curdir) - modules = {} - option_dict = self.distribution.get_option_dict('build_sphinx') - source_dir = os.path.join(option_dict['source_dir'][1], 'api') - if not os.path.exists(source_dir): - os.makedirs(source_dir) - for pkg in self.distribution.packages: - if '.' not in pkg: - os.path.walk(pkg, _find_modules, modules) - module_list = modules.keys() - module_list.sort() - autoindex_filename = os.path.join(source_dir, 'autoindex.rst') - with open(autoindex_filename, 'w') as autoindex: - autoindex.write(""".. toctree:: - :maxdepth: 1 - -""") - for module in module_list: - output_filename = os.path.join(source_dir, - "%s.rst" % module) - heading = "The :mod:`%s` Module" % module - underline = "=" * len(heading) - values = dict(module=module, heading=heading, - underline=underline) - - print "Generating %s" % output_filename - with open(output_filename, 'w') as output_file: - output_file.write(_rst_template % values) - autoindex.write(" %s.rst\n" % module) - - def run(self): - if not os.getenv('SPHINX_DEBUG'): - self.generate_autoindex() - - for builder in self.builders: - self.builder = builder - self.finalize_options() - self.project = self.distribution.get_name() - self.version = self.distribution.get_version() - self.release = self.distribution.get_version() - BuildDoc.run(self) - - class LocalBuildLatex(LocalBuildDoc): - builders = ['latex'] - - cmdclass['build_sphinx'] = LocalBuildDoc - cmdclass['build_sphinx_latex'] = LocalBuildLatex - except ImportError: - pass - - return cmdclass - - -def _get_revno(git_dir): - """Return the number of commits since the most recent tag. - - We use git-describe to find this out, but if there are no - tags then we fall back to counting commits since the beginning - of time. - """ - describe = _run_shell_command( - "git --git-dir=%s describe --always" % git_dir) - if "-" in describe: - return describe.rsplit("-", 2)[-2] - - # no tags found - revlist = _run_shell_command( - "git --git-dir=%s rev-list --abbrev-commit HEAD" % git_dir) - return len(revlist.splitlines()) - - -def _get_version_from_git(pre_version): - """Return a version which is equal to the tag that's on the current - revision if there is one, or tag plus number of additional revisions - if the current revision has no tag.""" - - git_dir = _get_git_directory() - if git_dir: - if pre_version: - try: - return _run_shell_command( - "git --git-dir=" + git_dir + " describe --exact-match", - throw_on_error=True).replace('-', '.') - except Exception: - sha = _run_shell_command( - "git --git-dir=" + git_dir + " log -n1 --pretty=format:%h") - return "%s.a%s.g%s" % (pre_version, _get_revno(git_dir), sha) - else: - return _run_shell_command( - "git --git-dir=" + git_dir + " describe --always").replace( - '-', '.') - return None - - -def _get_version_from_pkg_info(package_name): - """Get the version from PKG-INFO file if we can.""" - try: - pkg_info_file = open('PKG-INFO', 'r') - except (IOError, OSError): - return None - try: - pkg_info = email.message_from_file(pkg_info_file) - except email.MessageError: - return None - # Check to make sure we're in our own dir - if pkg_info.get('Name', None) != package_name: - return None - return pkg_info.get('Version', None) - - -def get_version(package_name, pre_version=None): - """Get the version of the project. First, try getting it from PKG-INFO, if - it exists. If it does, that means we're in a distribution tarball or that - install has happened. Otherwise, if there is no PKG-INFO file, pull the - version from git. - - We do not support setup.py version sanity in git archive tarballs, nor do - we support packagers directly sucking our git repo into theirs. We expect - that a source tarball be made from our git repo - or that if someone wants - to make a source tarball from a fork of our repo with additional tags in it - that they understand and desire the results of doing that. - """ - version = os.environ.get("OSLO_PACKAGE_VERSION", None) - if version: - return version - version = _get_version_from_pkg_info(package_name) - if version: - return version - version = _get_version_from_git(pre_version) - if version: - return version - raise Exception("Versioning for this project requires either an sdist" - " tarball, or access to an upstream git repository.") diff --git a/conductor/conductor/openstack/common/sslutils.py b/conductor/conductor/openstack/common/sslutils.py deleted file mode 100644 index 6ccbac87..00000000 --- a/conductor/conductor/openstack/common/sslutils.py +++ /dev/null @@ -1,80 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2013 IBM -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os -import ssl - -from oslo.config import cfg - -from conductor.openstack.common.gettextutils import _ - - -ssl_opts = [ - cfg.StrOpt('ca_file', - default=None, - help="CA certificate file to use to verify " - "connecting clients"), - cfg.StrOpt('cert_file', - default=None, - help="Certificate file to use when starting " - "the server securely"), - cfg.StrOpt('key_file', - default=None, - help="Private key file to use when starting " - "the server securely"), -] - - -CONF = cfg.CONF -CONF.register_opts(ssl_opts, "ssl") - - -def is_enabled(): - cert_file = CONF.ssl.cert_file - key_file = CONF.ssl.key_file - ca_file = CONF.ssl.ca_file - use_ssl = cert_file or key_file - - if cert_file and not os.path.exists(cert_file): - raise RuntimeError(_("Unable to find cert_file : %s") % cert_file) - - if ca_file and not os.path.exists(ca_file): - raise RuntimeError(_("Unable to find ca_file : %s") % ca_file) - - if key_file and not os.path.exists(key_file): - raise RuntimeError(_("Unable to find key_file : %s") % key_file) - - if use_ssl and (not cert_file or not key_file): - raise RuntimeError(_("When running server in SSL mode, you must " - "specify both a cert_file and key_file " - "option value in your configuration file")) - - return use_ssl - - -def wrap(sock): - ssl_kwargs = { - 'server_side': True, - 'certfile': CONF.ssl.cert_file, - 'keyfile': CONF.ssl.key_file, - 'cert_reqs': ssl.CERT_NONE, - } - - if CONF.ssl.ca_file: - ssl_kwargs['ca_certs'] = CONF.ssl.ca_file - ssl_kwargs['cert_reqs'] = ssl.CERT_REQUIRED - - return ssl.wrap_socket(sock, **ssl_kwargs) diff --git a/conductor/conductor/openstack/common/threadgroup.py b/conductor/conductor/openstack/common/threadgroup.py deleted file mode 100644 index 5c986aa9..00000000 --- a/conductor/conductor/openstack/common/threadgroup.py +++ /dev/null @@ -1,114 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from eventlet import greenlet -from eventlet import greenpool -from eventlet import greenthread - -from conductor.openstack.common import log as logging -from conductor.openstack.common import loopingcall - - -LOG = logging.getLogger(__name__) - - -def _thread_done(gt, *args, **kwargs): - """ Callback function to be passed to GreenThread.link() when we spawn() - Calls the :class:`ThreadGroup` to notify if. - - """ - kwargs['group'].thread_done(kwargs['thread']) - - -class Thread(object): - """ Wrapper around a greenthread, that holds a reference to the - :class:`ThreadGroup`. The Thread will notify the :class:`ThreadGroup` when - it has done so it can be removed from the threads list. - """ - def __init__(self, thread, group): - self.thread = thread - self.thread.link(_thread_done, group=group, thread=self) - - def stop(self): - self.thread.kill() - - def wait(self): - return self.thread.wait() - - -class ThreadGroup(object): - """ The point of the ThreadGroup classis to: - - * keep track of timers and greenthreads (making it easier to stop them - when need be). - * provide an easy API to add timers. - """ - def __init__(self, thread_pool_size=10): - self.pool = greenpool.GreenPool(thread_pool_size) - self.threads = [] - self.timers = [] - - def add_timer(self, interval, callback, initial_delay=None, - *args, **kwargs): - pulse = loopingcall.LoopingCall(callback, *args, **kwargs) - pulse.start(interval=interval, - initial_delay=initial_delay) - self.timers.append(pulse) - - def add_thread(self, callback, *args, **kwargs): - gt = self.pool.spawn(callback, *args, **kwargs) - th = Thread(gt, self) - self.threads.append(th) - - def thread_done(self, thread): - self.threads.remove(thread) - - def stop(self): - current = greenthread.getcurrent() - for x in self.threads: - if x is current: - # don't kill the current thread. - continue - try: - x.stop() - except Exception as ex: - LOG.exception(ex) - - for x in self.timers: - try: - x.stop() - except Exception as ex: - LOG.exception(ex) - self.timers = [] - - def wait(self): - for x in self.timers: - try: - x.wait() - except greenlet.GreenletExit: - pass - except Exception as ex: - LOG.exception(ex) - current = greenthread.getcurrent() - for x in self.threads: - if x is current: - continue - try: - x.wait() - except greenlet.GreenletExit: - pass - except Exception as ex: - LOG.exception(ex) diff --git a/conductor/conductor/openstack/common/timeutils.py b/conductor/conductor/openstack/common/timeutils.py deleted file mode 100644 index 60943659..00000000 --- a/conductor/conductor/openstack/common/timeutils.py +++ /dev/null @@ -1,186 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Time related utilities and helper functions. -""" - -import calendar -import datetime - -import iso8601 - - -# ISO 8601 extended time format with microseconds -_ISO8601_TIME_FORMAT_SUBSECOND = '%Y-%m-%dT%H:%M:%S.%f' -_ISO8601_TIME_FORMAT = '%Y-%m-%dT%H:%M:%S' -PERFECT_TIME_FORMAT = _ISO8601_TIME_FORMAT_SUBSECOND - - -def isotime(at=None, subsecond=False): - """Stringify time in ISO 8601 format""" - if not at: - at = utcnow() - st = at.strftime(_ISO8601_TIME_FORMAT - if not subsecond - else _ISO8601_TIME_FORMAT_SUBSECOND) - tz = at.tzinfo.tzname(None) if at.tzinfo else 'UTC' - st += ('Z' if tz == 'UTC' else tz) - return st - - -def parse_isotime(timestr): - """Parse time from ISO 8601 format""" - try: - return iso8601.parse_date(timestr) - except iso8601.ParseError as e: - raise ValueError(e.message) - except TypeError as e: - raise ValueError(e.message) - - -def strtime(at=None, fmt=PERFECT_TIME_FORMAT): - """Returns formatted utcnow.""" - if not at: - at = utcnow() - return at.strftime(fmt) - - -def parse_strtime(timestr, fmt=PERFECT_TIME_FORMAT): - """Turn a formatted time back into a datetime.""" - return datetime.datetime.strptime(timestr, fmt) - - -def normalize_time(timestamp): - """Normalize time in arbitrary timezone to UTC naive object""" - offset = timestamp.utcoffset() - if offset is None: - return timestamp - return timestamp.replace(tzinfo=None) - offset - - -def is_older_than(before, seconds): - """Return True if before is older than seconds.""" - if isinstance(before, basestring): - before = parse_strtime(before).replace(tzinfo=None) - return utcnow() - before > datetime.timedelta(seconds=seconds) - - -def is_newer_than(after, seconds): - """Return True if after is newer than seconds.""" - if isinstance(after, basestring): - after = parse_strtime(after).replace(tzinfo=None) - return after - utcnow() > datetime.timedelta(seconds=seconds) - - -def utcnow_ts(): - """Timestamp version of our utcnow function.""" - return calendar.timegm(utcnow().timetuple()) - - -def utcnow(): - """Overridable version of utils.utcnow.""" - if utcnow.override_time: - try: - return utcnow.override_time.pop(0) - except AttributeError: - return utcnow.override_time - return datetime.datetime.utcnow() - - -def iso8601_from_timestamp(timestamp): - """Returns a iso8601 formated date from timestamp""" - return isotime(datetime.datetime.utcfromtimestamp(timestamp)) - - -utcnow.override_time = None - - -def set_time_override(override_time=datetime.datetime.utcnow()): - """ - Override utils.utcnow to return a constant time or a list thereof, - one at a time. - """ - utcnow.override_time = override_time - - -def advance_time_delta(timedelta): - """Advance overridden time using a datetime.timedelta.""" - assert(not utcnow.override_time is None) - try: - for dt in utcnow.override_time: - dt += timedelta - except TypeError: - utcnow.override_time += timedelta - - -def advance_time_seconds(seconds): - """Advance overridden time by seconds.""" - advance_time_delta(datetime.timedelta(0, seconds)) - - -def clear_time_override(): - """Remove the overridden time.""" - utcnow.override_time = None - - -def marshall_now(now=None): - """Make an rpc-safe datetime with microseconds. - - Note: tzinfo is stripped, but not required for relative times.""" - if not now: - now = utcnow() - return dict(day=now.day, month=now.month, year=now.year, hour=now.hour, - minute=now.minute, second=now.second, - microsecond=now.microsecond) - - -def unmarshall_time(tyme): - """Unmarshall a datetime dict.""" - return datetime.datetime(day=tyme['day'], - month=tyme['month'], - year=tyme['year'], - hour=tyme['hour'], - minute=tyme['minute'], - second=tyme['second'], - microsecond=tyme['microsecond']) - - -def delta_seconds(before, after): - """ - Compute the difference in seconds between two date, time, or - datetime objects (as a float, to microsecond resolution). - """ - delta = after - before - try: - return delta.total_seconds() - except AttributeError: - return ((delta.days * 24 * 3600) + delta.seconds + - float(delta.microseconds) / (10 ** 6)) - - -def is_soon(dt, window): - """ - Determines if time is going to happen in the next window seconds. - - :params dt: the time - :params window: minimum seconds to remain to consider the time not soon - - :return: True if expiration is within the given duration - """ - soon = (utcnow() + datetime.timedelta(seconds=window)) - return normalize_time(dt) <= soon diff --git a/conductor/conductor/openstack/common/uuidutils.py b/conductor/conductor/openstack/common/uuidutils.py deleted file mode 100644 index 7608acb9..00000000 --- a/conductor/conductor/openstack/common/uuidutils.py +++ /dev/null @@ -1,39 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright (c) 2012 Intel Corporation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -UUID related utilities and helper functions. -""" - -import uuid - - -def generate_uuid(): - return str(uuid.uuid4()) - - -def is_uuid_like(val): - """Returns validation of a value as a UUID. - - For our purposes, a UUID is a canonical form string: - aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa - - """ - try: - return str(uuid.UUID(val)) == val - except (TypeError, ValueError, AttributeError): - return False diff --git a/conductor/conductor/openstack/common/version.py b/conductor/conductor/openstack/common/version.py deleted file mode 100644 index 080a89e2..00000000 --- a/conductor/conductor/openstack/common/version.py +++ /dev/null @@ -1,94 +0,0 @@ - -# Copyright 2012 OpenStack Foundation -# Copyright 2012-2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Utilities for consuming the version from pkg_resources. -""" - -import pkg_resources - - -class VersionInfo(object): - - def __init__(self, package): - """Object that understands versioning for a package - :param package: name of the python package, such as glance, or - python-glanceclient - """ - self.package = package - self.release = None - self.version = None - self._cached_version = None - - def __str__(self): - """Make the VersionInfo object behave like a string.""" - return self.version_string() - - def __repr__(self): - """Include the name.""" - return "VersionInfo(%s:%s)" % (self.package, self.version_string()) - - def _get_version_from_pkg_resources(self): - """Get the version of the package from the pkg_resources record - associated with the package.""" - try: - requirement = pkg_resources.Requirement.parse(self.package) - provider = pkg_resources.get_provider(requirement) - return provider.version - except pkg_resources.DistributionNotFound: - # The most likely cause for this is running tests in a tree - # produced from a tarball where the package itself has not been - # installed into anything. Revert to setup-time logic. - from conductor.openstack.common import setup - return setup.get_version(self.package) - - def release_string(self): - """Return the full version of the package including suffixes indicating - VCS status. - """ - if self.release is None: - self.release = self._get_version_from_pkg_resources() - - return self.release - - def version_string(self): - """Return the short version minus any alpha/beta tags.""" - if self.version is None: - parts = [] - for part in self.release_string().split('.'): - if part[0].isdigit(): - parts.append(part) - else: - break - self.version = ".".join(parts) - - return self.version - - # Compatibility functions - canonical_version_string = version_string - version_string_with_vcs = release_string - - def cached_version_string(self, prefix=""): - """Generate an object which will expand in a string context to - the results of version_string(). We do this so that don't - call into pkg_resources every time we start up a program when - passing version information into the CONF constructor, but - rather only do the calculation when and if a version is requested - """ - if not self._cached_version: - self._cached_version = "%s%s" % (prefix, - self.version_string()) - return self._cached_version diff --git a/conductor/conductor/openstack/common/wsgi.py b/conductor/conductor/openstack/common/wsgi.py deleted file mode 100644 index 9df31881..00000000 --- a/conductor/conductor/openstack/common/wsgi.py +++ /dev/null @@ -1,797 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Utility methods for working with WSGI servers.""" - -import eventlet -eventlet.patcher.monkey_patch(all=False, socket=True) - -import datetime -import errno -import socket -import sys -import time - -import eventlet.wsgi -from oslo.config import cfg -import routes -import routes.middleware -import webob.dec -import webob.exc -from xml.dom import minidom -from xml.parsers import expat - -from conductor.openstack.common import exception -from conductor.openstack.common.gettextutils import _ -from conductor.openstack.common import jsonutils -from conductor.openstack.common import log as logging -from conductor.openstack.common import service -from conductor.openstack.common import sslutils -from conductor.openstack.common import xmlutils - -socket_opts = [ - cfg.IntOpt('backlog', - default=4096, - help="Number of backlog requests to configure the socket with"), - cfg.IntOpt('tcp_keepidle', - default=600, - help="Sets the value of TCP_KEEPIDLE in seconds for each " - "server socket. Not supported on OS X."), -] - -CONF = cfg.CONF -CONF.register_opts(socket_opts) - -LOG = logging.getLogger(__name__) - - -def run_server(application, port, **kwargs): - """Run a WSGI server with the given application.""" - sock = eventlet.listen(('0.0.0.0', port)) - eventlet.wsgi.server(sock, application, **kwargs) - - -class Service(service.Service): - """ - Provides a Service API for wsgi servers. - - This gives us the ability to launch wsgi servers with the - Launcher classes in service.py. - """ - - def __init__(self, application, port, - host='0.0.0.0', backlog=4096, threads=1000): - self.application = application - self._port = port - self._host = host - self._backlog = backlog if backlog else CONF.backlog - super(Service, self).__init__(threads) - - def _get_socket(self, host, port, backlog): - # TODO(dims): eventlet's green dns/socket module does not actually - # support IPv6 in getaddrinfo(). We need to get around this in the - # future or monitor upstream for a fix - info = socket.getaddrinfo(host, - port, - socket.AF_UNSPEC, - socket.SOCK_STREAM)[0] - family = info[0] - bind_addr = info[-1] - - sock = None - retry_until = time.time() + 30 - while not sock and time.time() < retry_until: - try: - sock = eventlet.listen(bind_addr, - backlog=backlog, - family=family) - if sslutils.is_enabled(): - sock = sslutils.wrap(sock) - - except socket.error, err: - if err.args[0] != errno.EADDRINUSE: - raise - eventlet.sleep(0.1) - if not sock: - raise RuntimeError(_("Could not bind to %(host)s:%(port)s " - "after trying for 30 seconds") % - {'host': host, 'port': port}) - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - # sockets can hang around forever without keepalive - sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) - - # This option isn't available in the OS X version of eventlet - if hasattr(socket, 'TCP_KEEPIDLE'): - sock.setsockopt(socket.IPPROTO_TCP, - socket.TCP_KEEPIDLE, - CONF.tcp_keepidle) - - return sock - - def start(self): - """Start serving this service using the provided server instance. - - :returns: None - - """ - super(Service, self).start() - self._socket = self._get_socket(self._host, self._port, self._backlog) - self.tg.add_thread(self._run, self.application, self._socket) - - @property - def backlog(self): - return self._backlog - - @property - def host(self): - return self._socket.getsockname()[0] if self._socket else self._host - - @property - def port(self): - return self._socket.getsockname()[1] if self._socket else self._port - - def stop(self): - """Stop serving this API. - - :returns: None - - """ - super(Service, self).stop() - - def _run(self, application, socket): - """Start a WSGI server in a new green thread.""" - logger = logging.getLogger('eventlet.wsgi') - eventlet.wsgi.server(socket, - application, - custom_pool=self.tg.pool, - log=logging.WritableLogger(logger)) - - -class Middleware(object): - """ - Base WSGI middleware wrapper. These classes require an application to be - initialized that will be called next. By default the middleware will - simply call its wrapped app, or you can override __call__ to customize its - behavior. - """ - - def __init__(self, application): - self.application = application - - def process_request(self, req): - """ - Called on each request. - - If this returns None, the next application down the stack will be - executed. If it returns a response then that response will be returned - and execution will stop here. - """ - return None - - def process_response(self, response): - """Do whatever you'd like to the response.""" - return response - - @webob.dec.wsgify - def __call__(self, req): - response = self.process_request(req) - if response: - return response - response = req.get_response(self.application) - return self.process_response(response) - - -class Debug(Middleware): - """ - Helper class that can be inserted into any WSGI application chain - to get information about the request and response. - """ - - @webob.dec.wsgify - def __call__(self, req): - print ("*" * 40) + " REQUEST ENVIRON" - for key, value in req.environ.items(): - print key, "=", value - print - resp = req.get_response(self.application) - - print ("*" * 40) + " RESPONSE HEADERS" - for (key, value) in resp.headers.iteritems(): - print key, "=", value - print - - resp.app_iter = self.print_generator(resp.app_iter) - - return resp - - @staticmethod - def print_generator(app_iter): - """ - Iterator that prints the contents of a wrapper string iterator - when iterated. - """ - print ("*" * 40) + " BODY" - for part in app_iter: - sys.stdout.write(part) - sys.stdout.flush() - yield part - print - - -class Router(object): - - """ - WSGI middleware that maps incoming requests to WSGI apps. - """ - - def __init__(self, mapper): - """ - Create a router for the given routes.Mapper. - - Each route in `mapper` must specify a 'controller', which is a - WSGI app to call. You'll probably want to specify an 'action' as - well and have your controller be a wsgi.Controller, who will route - the request to the action method. - - Examples: - mapper = routes.Mapper() - sc = ServerController() - - # Explicit mapping of one route to a controller+action - mapper.connect(None, "/svrlist", controller=sc, action="list") - - # Actions are all implicitly defined - mapper.resource("server", "servers", controller=sc) - - # Pointing to an arbitrary WSGI app. You can specify the - # {path_info:.*} parameter so the target app can be handed just that - # section of the URL. - mapper.connect(None, "/v1.0/{path_info:.*}", controller=BlogApp()) - """ - self.map = mapper - self._router = routes.middleware.RoutesMiddleware(self._dispatch, - self.map) - - @webob.dec.wsgify - def __call__(self, req): - """ - Route the incoming request to a controller based on self.map. - If no match, return a 404. - """ - return self._router - - @staticmethod - @webob.dec.wsgify - def _dispatch(req): - """ - Called by self._router after matching the incoming request to a route - and putting the information into req.environ. Either returns 404 - or the routed WSGI app's response. - """ - match = req.environ['wsgiorg.routing_args'][1] - if not match: - return webob.exc.HTTPNotFound() - app = match['controller'] - return app - - -class Request(webob.Request): - """Add some Openstack API-specific logic to the base webob.Request.""" - - default_request_content_types = ('application/json', 'application/xml') - default_accept_types = ('application/json', 'application/xml') - default_accept_type = 'application/json' - - def best_match_content_type(self, supported_content_types=None): - """Determine the requested response content-type. - - Based on the query extension then the Accept header. - Defaults to default_accept_type if we don't find a preference - - """ - supported_content_types = (supported_content_types or - self.default_accept_types) - - parts = self.path.rsplit('.', 1) - if len(parts) > 1: - ctype = 'application/{0}'.format(parts[1]) - if ctype in supported_content_types: - return ctype - - bm = self.accept.best_match(supported_content_types) - return bm or self.default_accept_type - - def get_content_type(self, allowed_content_types=None): - """Determine content type of the request body. - - Does not do any body introspection, only checks header - - """ - if "Content-Type" not in self.headers: - return None - - content_type = self.content_type - allowed_content_types = (allowed_content_types or - self.default_request_content_types) - - if content_type not in allowed_content_types: - raise exception.InvalidContentType(content_type=content_type) - return content_type - - -class Resource(object): - """ - WSGI app that handles (de)serialization and controller dispatch. - - Reads routing information supplied by RoutesMiddleware and calls - the requested action method upon its deserializer, controller, - and serializer. Those three objects may implement any of the basic - controller action methods (create, update, show, index, delete) - along with any that may be specified in the api router. A 'default' - method may also be implemented to be used in place of any - non-implemented actions. Deserializer methods must accept a request - argument and return a dictionary. Controller methods must accept a - request argument. Additionally, they must also accept keyword - arguments that represent the keys returned by the Deserializer. They - may raise a webob.exc exception or return a dict, which will be - serialized by requested content type. - """ - def __init__(self, controller, deserializer=None, serializer=None): - """ - :param controller: object that implement methods created by routes lib - :param deserializer: object that supports webob request deserialization - through controller-like actions - :param serializer: object that supports webob response serialization - through controller-like actions - """ - self.controller = controller - self.serializer = serializer or ResponseSerializer() - self.deserializer = deserializer or RequestDeserializer() - - @webob.dec.wsgify(RequestClass=Request) - def __call__(self, request): - """WSGI method that controls (de)serialization and method dispatch.""" - - try: - action, action_args, accept = self.deserialize_request(request) - except exception.InvalidContentType: - msg = _("Unsupported Content-Type") - return webob.exc.HTTPUnsupportedMediaType(explanation=msg) - except exception.MalformedRequestBody: - msg = _("Malformed request body") - return webob.exc.HTTPBadRequest(explanation=msg) - - action_result = self.execute_action(action, request, **action_args) - try: - return self.serialize_response(action, action_result, accept) - # return unserializable result (typically a webob exc) - except Exception: - return action_result - - def deserialize_request(self, request): - return self.deserializer.deserialize(request) - - def serialize_response(self, action, action_result, accept): - return self.serializer.serialize(action_result, accept, action) - - def execute_action(self, action, request, **action_args): - return self.dispatch(self.controller, action, request, **action_args) - - def dispatch(self, obj, action, *args, **kwargs): - """Find action-specific method on self and call it.""" - try: - method = getattr(obj, action) - except AttributeError: - method = getattr(obj, 'default') - - return method(*args, **kwargs) - - def get_action_args(self, request_environment): - """Parse dictionary created by routes library.""" - try: - args = request_environment['wsgiorg.routing_args'][1].copy() - except Exception: - return {} - - try: - del args['controller'] - except KeyError: - pass - - try: - del args['format'] - except KeyError: - pass - - return args - - -class ActionDispatcher(object): - """Maps method name to local methods through action name.""" - - def dispatch(self, *args, **kwargs): - """Find and call local method.""" - action = kwargs.pop('action', 'default') - action_method = getattr(self, str(action), self.default) - return action_method(*args, **kwargs) - - def default(self, data): - raise NotImplementedError() - - -class DictSerializer(ActionDispatcher): - """Default request body serialization""" - - def serialize(self, data, action='default'): - return self.dispatch(data, action=action) - - def default(self, data): - return "" - - -class JSONDictSerializer(DictSerializer): - """Default JSON request body serialization""" - - def default(self, data): - def sanitizer(obj): - if isinstance(obj, datetime.datetime): - _dtime = obj - datetime.timedelta(microseconds=obj.microsecond) - return _dtime.isoformat() - return unicode(obj) - return jsonutils.dumps(data, default=sanitizer) - - -class XMLDictSerializer(DictSerializer): - - def __init__(self, metadata=None, xmlns=None): - """ - :param metadata: information needed to deserialize xml into - a dictionary. - :param xmlns: XML namespace to include with serialized xml - """ - super(XMLDictSerializer, self).__init__() - self.metadata = metadata or {} - self.xmlns = xmlns - - def default(self, data): - # We expect data to contain a single key which is the XML root. - root_key = data.keys()[0] - doc = minidom.Document() - node = self._to_xml_node(doc, self.metadata, root_key, data[root_key]) - - return self.to_xml_string(node) - - def to_xml_string(self, node, has_atom=False): - self._add_xmlns(node, has_atom) - return node.toprettyxml(indent=' ', encoding='UTF-8') - - #NOTE (ameade): the has_atom should be removed after all of the - # xml serializers and view builders have been updated to the current - # spec that required all responses include the xmlns:atom, the has_atom - # flag is to prevent current tests from breaking - def _add_xmlns(self, node, has_atom=False): - if self.xmlns is not None: - node.setAttribute('xmlns', self.xmlns) - if has_atom: - node.setAttribute('xmlns:atom', "http://www.w3.org/2005/Atom") - - def _to_xml_node(self, doc, metadata, nodename, data): - """Recursive method to convert data members to XML nodes.""" - result = doc.createElement(nodename) - - # Set the xml namespace if one is specified - # TODO(justinsb): We could also use prefixes on the keys - xmlns = metadata.get('xmlns', None) - if xmlns: - result.setAttribute('xmlns', xmlns) - - #TODO(bcwaldon): accomplish this without a type-check - if type(data) is list: - collections = metadata.get('list_collections', {}) - if nodename in collections: - metadata = collections[nodename] - for item in data: - node = doc.createElement(metadata['item_name']) - node.setAttribute(metadata['item_key'], str(item)) - result.appendChild(node) - return result - singular = metadata.get('plurals', {}).get(nodename, None) - if singular is None: - if nodename.endswith('s'): - singular = nodename[:-1] - else: - singular = 'item' - for item in data: - node = self._to_xml_node(doc, metadata, singular, item) - result.appendChild(node) - #TODO(bcwaldon): accomplish this without a type-check - elif type(data) is dict: - collections = metadata.get('dict_collections', {}) - if nodename in collections: - metadata = collections[nodename] - for k, v in data.items(): - node = doc.createElement(metadata['item_name']) - node.setAttribute(metadata['item_key'], str(k)) - text = doc.createTextNode(str(v)) - node.appendChild(text) - result.appendChild(node) - return result - attrs = metadata.get('attributes', {}).get(nodename, {}) - for k, v in data.items(): - if k in attrs: - result.setAttribute(k, str(v)) - else: - node = self._to_xml_node(doc, metadata, k, v) - result.appendChild(node) - else: - # Type is atom - node = doc.createTextNode(str(data)) - result.appendChild(node) - return result - - def _create_link_nodes(self, xml_doc, links): - link_nodes = [] - for link in links: - link_node = xml_doc.createElement('atom:link') - link_node.setAttribute('rel', link['rel']) - link_node.setAttribute('href', link['href']) - if 'type' in link: - link_node.setAttribute('type', link['type']) - link_nodes.append(link_node) - return link_nodes - - -class ResponseHeadersSerializer(ActionDispatcher): - """Default response headers serialization""" - - def serialize(self, response, data, action): - self.dispatch(response, data, action=action) - - def default(self, response, data): - response.status_int = 200 - - -class ResponseSerializer(object): - """Encode the necessary pieces into a response object""" - - def __init__(self, body_serializers=None, headers_serializer=None): - self.body_serializers = { - 'application/xml': XMLDictSerializer(), - 'application/json': JSONDictSerializer(), - } - self.body_serializers.update(body_serializers or {}) - - self.headers_serializer = (headers_serializer or - ResponseHeadersSerializer()) - - def serialize(self, response_data, content_type, action='default'): - """Serialize a dict into a string and wrap in a wsgi.Request object. - - :param response_data: dict produced by the Controller - :param content_type: expected mimetype of serialized response body - - """ - response = webob.Response() - self.serialize_headers(response, response_data, action) - self.serialize_body(response, response_data, content_type, action) - return response - - def serialize_headers(self, response, data, action): - self.headers_serializer.serialize(response, data, action) - - def serialize_body(self, response, data, content_type, action): - response.headers['Content-Type'] = content_type - if data is not None: - serializer = self.get_body_serializer(content_type) - response.body = serializer.serialize(data, action) - - def get_body_serializer(self, content_type): - try: - return self.body_serializers[content_type] - except (KeyError, TypeError): - raise exception.InvalidContentType(content_type=content_type) - - -class RequestHeadersDeserializer(ActionDispatcher): - """Default request headers deserializer""" - - def deserialize(self, request, action): - return self.dispatch(request, action=action) - - def default(self, request): - return {} - - -class RequestDeserializer(object): - """Break up a Request object into more useful pieces.""" - - def __init__(self, body_deserializers=None, headers_deserializer=None, - supported_content_types=None): - - self.supported_content_types = supported_content_types - - self.body_deserializers = { - 'application/xml': XMLDeserializer(), - 'application/json': JSONDeserializer(), - } - self.body_deserializers.update(body_deserializers or {}) - - self.headers_deserializer = (headers_deserializer or - RequestHeadersDeserializer()) - - def deserialize(self, request): - """Extract necessary pieces of the request. - - :param request: Request object - :returns: tuple of (expected controller action name, dictionary of - keyword arguments to pass to the controller, the expected - content type of the response) - - """ - action_args = self.get_action_args(request.environ) - action = action_args.pop('action', None) - - action_args.update(self.deserialize_headers(request, action)) - action_args.update(self.deserialize_body(request, action)) - - accept = self.get_expected_content_type(request) - - return (action, action_args, accept) - - def deserialize_headers(self, request, action): - return self.headers_deserializer.deserialize(request, action) - - def deserialize_body(self, request, action): - if not len(request.body) > 0: - LOG.debug(_("Empty body provided in request")) - return {} - - try: - content_type = request.get_content_type() - except exception.InvalidContentType: - LOG.debug(_("Unrecognized Content-Type provided in request")) - raise - - if content_type is None: - LOG.debug(_("No Content-Type provided in request")) - return {} - - try: - deserializer = self.get_body_deserializer(content_type) - except exception.InvalidContentType: - LOG.debug(_("Unable to deserialize body as provided Content-Type")) - raise - - return deserializer.deserialize(request.body, action) - - def get_body_deserializer(self, content_type): - try: - return self.body_deserializers[content_type] - except (KeyError, TypeError): - raise exception.InvalidContentType(content_type=content_type) - - def get_expected_content_type(self, request): - return request.best_match_content_type(self.supported_content_types) - - def get_action_args(self, request_environment): - """Parse dictionary created by routes library.""" - try: - args = request_environment['wsgiorg.routing_args'][1].copy() - except Exception: - return {} - - try: - del args['controller'] - except KeyError: - pass - - try: - del args['format'] - except KeyError: - pass - - return args - - -class TextDeserializer(ActionDispatcher): - """Default request body deserialization""" - - def deserialize(self, datastring, action='default'): - return self.dispatch(datastring, action=action) - - def default(self, datastring): - return {} - - -class JSONDeserializer(TextDeserializer): - - def _from_json(self, datastring): - try: - return jsonutils.loads(datastring) - except ValueError: - msg = _("cannot understand JSON") - raise exception.MalformedRequestBody(reason=msg) - - def default(self, datastring): - return {'body': self._from_json(datastring)} - - -class XMLDeserializer(TextDeserializer): - - def __init__(self, metadata=None): - """ - :param metadata: information needed to deserialize xml into - a dictionary. - """ - super(XMLDeserializer, self).__init__() - self.metadata = metadata or {} - - def _from_xml(self, datastring): - plurals = set(self.metadata.get('plurals', {})) - - try: - node = xmlutils.safe_minidom_parse_string(datastring).childNodes[0] - return {node.nodeName: self._from_xml_node(node, plurals)} - except expat.ExpatError: - msg = _("cannot understand XML") - raise exception.MalformedRequestBody(reason=msg) - - def _from_xml_node(self, node, listnames): - """Convert a minidom node to a simple Python type. - - :param listnames: list of XML node names whose subnodes should - be considered list items. - - """ - - if len(node.childNodes) == 1 and node.childNodes[0].nodeType == 3: - return node.childNodes[0].nodeValue - elif node.nodeName in listnames: - return [self._from_xml_node(n, listnames) for n in node.childNodes] - else: - result = dict() - for attr in node.attributes.keys(): - result[attr] = node.attributes[attr].nodeValue - for child in node.childNodes: - if child.nodeType != node.TEXT_NODE: - result[child.nodeName] = self._from_xml_node(child, - listnames) - return result - - def find_first_child_named(self, parent, name): - """Search a nodes children for the first child with a given name""" - for node in parent.childNodes: - if node.nodeName == name: - return node - return None - - def find_children_named(self, parent, name): - """Return all of a nodes children who have the given name""" - for node in parent.childNodes: - if node.nodeName == name: - yield node - - def extract_text(self, node): - """Get the text field contained by the given node""" - if len(node.childNodes) == 1: - child = node.childNodes[0] - if child.nodeType == child.TEXT_NODE: - return child.nodeValue - return "" - - def default(self, datastring): - return {'body': self._from_xml(datastring)} diff --git a/conductor/conductor/openstack/common/xmlutils.py b/conductor/conductor/openstack/common/xmlutils.py deleted file mode 100644 index 33700485..00000000 --- a/conductor/conductor/openstack/common/xmlutils.py +++ /dev/null @@ -1,74 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2013 IBM -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from xml.dom import minidom -from xml.parsers import expat -from xml import sax -from xml.sax import expatreader - - -class ProtectedExpatParser(expatreader.ExpatParser): - """An expat parser which disables DTD's and entities by default.""" - - def __init__(self, forbid_dtd=True, forbid_entities=True, - *args, **kwargs): - # Python 2.x old style class - expatreader.ExpatParser.__init__(self, *args, **kwargs) - self.forbid_dtd = forbid_dtd - self.forbid_entities = forbid_entities - - def start_doctype_decl(self, name, sysid, pubid, has_internal_subset): - raise ValueError("Inline DTD forbidden") - - def entity_decl(self, entityName, is_parameter_entity, value, base, - systemId, publicId, notationName): - raise ValueError("<!ENTITY> entity declaration forbidden") - - def unparsed_entity_decl(self, name, base, sysid, pubid, notation_name): - # expat 1.2 - raise ValueError("<!ENTITY> unparsed entity forbidden") - - def external_entity_ref(self, context, base, systemId, publicId): - raise ValueError("<!ENTITY> external entity forbidden") - - def notation_decl(self, name, base, sysid, pubid): - raise ValueError("<!ENTITY> notation forbidden") - - def reset(self): - expatreader.ExpatParser.reset(self) - if self.forbid_dtd: - self._parser.StartDoctypeDeclHandler = self.start_doctype_decl - self._parser.EndDoctypeDeclHandler = None - if self.forbid_entities: - self._parser.EntityDeclHandler = self.entity_decl - self._parser.UnparsedEntityDeclHandler = self.unparsed_entity_decl - self._parser.ExternalEntityRefHandler = self.external_entity_ref - self._parser.NotationDeclHandler = self.notation_decl - try: - self._parser.SkippedEntityHandler = None - except AttributeError: - # some pyexpat versions do not support SkippedEntity - pass - - -def safe_minidom_parse_string(xml_string): - """Parse an XML string using minidom safely. - - """ - try: - return minidom.parseString(xml_string, parser=ProtectedExpatParser()) - except sax.SAXParseException: - raise expat.ExpatError() diff --git a/conductor/conductor/rabbitmq.py b/conductor/conductor/rabbitmq.py deleted file mode 100644 index f9d5d4c6..00000000 --- a/conductor/conductor/rabbitmq.py +++ /dev/null @@ -1,141 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from eventlet import patcher -puka = patcher.import_patched('puka') -#import puka -import anyjson -import config - - -class RmqClient(object): - def __init__(self): - settings = config.CONF.rabbitmq - self._client = puka.Client('amqp://{0}:{1}@{2}:{3}/{4}'.format( - settings.login, - settings.password, - settings.host, - settings.port, - settings.virtual_host - )) - self._connected = False - - def __enter__(self): - self.connect() - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - self.close() - return False - - def connect(self): - if not self._connected: - promise = self._client.connect() - self._client.wait(promise, timeout=10000) - self._connected = True - - def close(self): - if self._connected: - self._client.close() - self._connected = False - - def declare(self, queue, exchange=None): - promise = self._client.queue_declare(str(queue), durable=True) - self._client.wait(promise) - - if exchange: - promise = self._client.exchange_declare(str(exchange), durable=True) - self._client.wait(promise) - promise = self._client.queue_bind( - str(queue), str(exchange), routing_key=str(queue)) - self._client.wait(promise) - - def send(self, message, key, exchange='', timeout=None): - if not self._connected: - raise RuntimeError('Not connected to RabbitMQ') - - headers = { 'message_id': message.id } - - promise = self._client.basic_publish( - exchange=str(exchange), - routing_key=str(key), - body=anyjson.dumps(message.body), - headers=headers) - self._client.wait(promise, timeout=timeout) - - def open(self, queue): - if not self._connected: - raise RuntimeError('Not connected to RabbitMQ') - - return Subscription(self._client, queue) - - -class Subscription(object): - def __init__(self, client, queue): - self._client = client - self._queue = queue - self._promise = None - self._lastMessage = None - - def __enter__(self): - self._promise = self._client.basic_consume( - queue=self._queue, - prefetch_count=1) - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - self._ack_last() - promise = self._client.basic_cancel(self._promise) - self._client.wait(promise) - return False - - def _ack_last(self): - if self._lastMessage: - self._client.basic_ack(self._lastMessage) - self._lastMessage = None - - def get_message(self, timeout=None): - if not self._promise: - raise RuntimeError( - "Subscription object must be used within 'with' block") - self._ack_last() - self._lastMessage = self._client.wait(self._promise, timeout=timeout) - msg = Message() - msg.body = anyjson.loads(self._lastMessage['body']) - msg.id = self._lastMessage['headers'].get('message_id') - return msg - - -class Message(object): - def __init__(self): - self._body = {} - self._id = '' - - @property - def body(self): - return self._body - - @body.setter - def body(self, value): - self._body = value - - @property - def id(self): - return self._id - - @id.setter - def id(self, value): - self._id = value or '' - diff --git a/conductor/conductor/reporting.py b/conductor/conductor/reporting.py deleted file mode 100644 index d9d5fdf9..00000000 --- a/conductor/conductor/reporting.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import xml_code_engine -import rabbitmq - - -class Reporter(object): - def __init__(self, rmqclient, task_id, environment_id): - self._rmqclient = rmqclient - self._task_id = task_id - self._environment_id = environment_id - rmqclient.declare('task-reports') - - def _report_func(self, id, entity, text, **kwargs): - body = { - 'id': id, - 'entity': entity, - 'text': text, - 'environment_id': self._environment_id - } - - msg = rabbitmq.Message() - msg.body = body - msg.id = self._task_id - - self._rmqclient.send( - message=msg, - key='task-reports') - - -def _report_func(context, id, entity, text, **kwargs): - reporter = context['/reporter'] - return reporter._report_func(id, entity, text, **kwargs) - -xml_code_engine.XmlCodeEngine.register_function(_report_func, "report") diff --git a/conductor/conductor/version.py b/conductor/conductor/version.py deleted file mode 100644 index f17cad4c..00000000 --- a/conductor/conductor/version.py +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -from conductor.openstack.common import version as common_version - -version_info = common_version.VersionInfo('conductor') diff --git a/conductor/conductor/windows_agent.py b/conductor/conductor/windows_agent.py deleted file mode 100644 index 7470228c..00000000 --- a/conductor/conductor/windows_agent.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import xml_code_engine - -from openstack.common import log as logging -log = logging.getLogger(__name__) - - -def send_command(engine, context, body, template, service, host, mappings=None, - result=None, **kwargs): - if not mappings: - mappings = {} - command_dispatcher = context['/commandDispatcher'] - - def callback(result_value): - log.info( - 'Received result from {2} for {0}: {1}'.format( - template, result_value, host)) - if result is not None: - context[result] = result_value['Result'] - - success_handler = body.find('success') - if success_handler is not None: - engine.evaluate_content(success_handler, context) - - command_dispatcher.execute( - name='agent', template=template, mappings=mappings, - host=host, service=service, callback=callback) - - -xml_code_engine.XmlCodeEngine.register_function(send_command, "send-command") \ No newline at end of file diff --git a/conductor/conductor/workflow.py b/conductor/conductor/workflow.py deleted file mode 100644 index 773a7863..00000000 --- a/conductor/conductor/workflow.py +++ /dev/null @@ -1,190 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import jsonpath -import re -import types - -import function_context -import xml_code_engine - - -class Workflow(object): - def __init__(self, filename, data, command_dispatcher, config, reporter): - self._data = data - self._engine = xml_code_engine.XmlCodeEngine() - with open(filename) as xml: - self._engine.load(xml) - self._command_dispatcher = command_dispatcher - self._config = config - self._reporter = reporter - - def execute(self): - context = function_context.Context() - context['/dataSource'] = self._data - context['/commandDispatcher'] = self._command_dispatcher - context['/config'] = self._config - context['/reporter'] = self._reporter - return self._engine.execute(context) - - @staticmethod - def _get_path(obj, path, create_non_existing=False): - current = obj - for part in path: - if isinstance(current, types.ListType): - current = current[int(part)] - elif isinstance(current, types.DictionaryType): - if part not in current: - if create_non_existing: - current[part] = {} - else: - return None - current = current[part] - else: - raise ValueError() - - return current - - @staticmethod - def _set_path(obj, path, value): - current = Workflow._get_path(obj, path[:-1], True) - if isinstance(current, types.ListType): - current[int(path[-1])] = value - elif isinstance(current, types.DictionaryType): - current[path[-1]] = value - else: - raise ValueError() - - @staticmethod - def _get_relative_position(path, context): - position = context['__dataSource_currentPosition'] or [] - - index = 0 - for c in path: - if c == ':': - if len(position) > 0: - position = position[:-1] - elif c == '/': - position = [] - else: - break - - index += 1 - - return position, path[index:] - - @staticmethod - def _correct_position(path, context): - position, suffix = Workflow._get_relative_position(path, context) - - if not suffix: - return position - else: - return position + suffix.split('.') - - @staticmethod - def _select_func(context, path='', source=None, **kwargs): - - if path.startswith('##'): - config = context['/config'] - return config[path[2:]] - elif path.startswith('#'): - return context[path[1:]] - - if source is not None: - return Workflow._get_path( - context[source], path.split('.')) - else: - return Workflow._get_path( - context['/dataSource'], - Workflow._correct_position(path, context)) - - @staticmethod - def _set_func(path, context, body, engine, target=None, **kwargs): - body_data = engine.evaluate_content(body, context) - - if path.startswith('##'): - raise RuntimeError('Cannot modify config from XML-code') - elif path.startswith('#'): - context[':' + path[1:]] = body_data - return - - if target: - data = context[target] - position = path.split('.') - if Workflow._get_path(data, position) != body_data: - Workflow._set_path(data, position, body_data) - context['/hasSideEffects'] = True - - else: - data = context['/dataSource'] - new_position = Workflow._correct_position(path, context) - if Workflow._get_path(data, new_position) != body_data: - Workflow._set_path(data, new_position, body_data) - context['/hasSideEffects'] = True - - @staticmethod - def _rule_func(match, context, body, engine, limit=0, name=None, **kwargs): - position = context['__dataSource_currentPosition'] or [] - - position, match = Workflow._get_relative_position(match, context) - data = Workflow._get_path(context['/dataSource'], position) - match = re.sub(r'@\.([\w.]+)', - r"Workflow._get_path(@, '\1'.split('.'))", match) - match = match.replace('$.', '$[*].') - selected = jsonpath.jsonpath([data], match, 'IPATH') or [] - index = 0 - for found_match in selected: - if 0 < int(limit) <= index: - break - index += 1 - new_position = position + found_match[1:] - context['__dataSource_currentPosition'] = new_position - context['__dataSource_currentObj'] = Workflow._get_path( - context['/dataSource'], new_position) - for element in body: - if element.tag == 'empty': - continue - engine.evaluate(element, context) - if element.tag == 'rule' and context['/hasSideEffects']: - break - if not index: - empty_handler = body.find('empty') - if empty_handler is not None: - - engine.evaluate_content(empty_handler, context) - - - @staticmethod - def _workflow_func(context, body, engine, **kwargs): - context['/hasSideEffects'] = False - for element in body: - engine.evaluate(element, context) - if element.tag == 'rule' and context['/hasSideEffects']: - return True - return False - - -xml_code_engine.XmlCodeEngine.register_function( - Workflow._rule_func, 'rule') - -xml_code_engine.XmlCodeEngine.register_function( - Workflow._workflow_func, 'workflow') - -xml_code_engine.XmlCodeEngine.register_function( - Workflow._set_func, 'set') - -xml_code_engine.XmlCodeEngine.register_function( - Workflow._select_func, 'select') diff --git a/conductor/conductor/xml_code_engine.py b/conductor/conductor/xml_code_engine.py deleted file mode 100644 index 8661ead4..00000000 --- a/conductor/conductor/xml_code_engine.py +++ /dev/null @@ -1,137 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import xml.etree.ElementTree as etree -import types - -import function_context - - -class XmlCodeEngine(object): - _functionMap = {} - - def __init__(self): - self._document = None - - def load(self, file_obj): - self._document = etree.parse(file_obj) - - @staticmethod - def register_function(func, name): - XmlCodeEngine._functionMap[name] = func - - def _execute_function(self, name, element, parent_context): - if name == 'parameter': - return None - - if name not in self._functionMap: - raise KeyError('Unknown function %s' % name) - - definition = self._functionMap[name] - context = function_context.Context(parent_context) - args = {'engine': self, 'body': element, 'context': context} - - for key, value in element.items(): - args[key] = value - - for parameter in element.findall('parameter'): - args[parameter.get('name')] = self.evaluate_content( - parameter, context) - - return definition(**args) - - def evaluate(self, element, parent_context): - return self._execute_function(element.tag, element, parent_context) - - def evaluate_content(self, element, context): - parts = [element.text or ''] - do_strip = False - for sub_element in element: - if sub_element.tag == 'parameter': - continue - do_strip = True - parts.append(self._execute_function( - sub_element.tag, sub_element, context)) - parts.append(sub_element.tail or '') - - result = [] - - for t in parts: - if not isinstance(t, types.StringTypes): - result.append(t) - - return_value = result - if len(result) == 0: - return_value = ''.join(parts) - if do_strip: - return_value = return_value.strip() - elif len(result) == 1: - return_value = result[0] - - return return_value - - def execute(self, parent_context=None): - root = self._document.getroot() - return self.evaluate(root, parent_context) - - -def _dict_func(engine, body, context, **kwargs): - result = {} - for item in body: - key = item.get('name') - value = engine.evaluate_content(item, context) - result[key] = value - return result - - -def _array_func(engine, body, context, **kwargs): - result = [] - for item in body: - result.append(engine.evaluate(item, context)) - return result - - -def _text_func(engine, body, context, **kwargs): - return str(engine.evaluate_content(body, context)) - - -def _int_func(engine, body, context, **kwargs): - return int(engine.evaluate_content(body, context)) - - -def _function_func(engine, body, context, **kwargs): - return lambda: engine.evaluate_content(body, context) - - -def _null_func(**kwargs): - return None - - -def _true_func(**kwargs): - return True - - -def _false_func(**kwargs): - return False - - -XmlCodeEngine.register_function(_dict_func, "map") -XmlCodeEngine.register_function(_array_func, "list") -XmlCodeEngine.register_function(_text_func, "text") -XmlCodeEngine.register_function(_int_func, "int") -XmlCodeEngine.register_function(_function_func, "function") -XmlCodeEngine.register_function(_null_func, "null") -XmlCodeEngine.register_function(_true_func, "true") -XmlCodeEngine.register_function(_false_func, "false") diff --git a/conductor/data/init.ps1 b/conductor/data/init.ps1 deleted file mode 100644 index 0e6cb212..00000000 --- a/conductor/data/init.ps1 +++ /dev/null @@ -1,33 +0,0 @@ -#ps1 - -$WindowsAgentConfigBase64 = '%WINDOWS_AGENT_CONFIG_BASE64%' -$WindowsAgentConfigFile = "C:\Keero\Agent\WindowsAgent.exe.config" - -$NewComputerName = '%INTERNAL_HOSTNAME%' - -$RestartRequired = $false - -Import-Module CoreFunctions - -Write-Log "Updating Keero Windows Agent." -Stop-Service "Keero Agent" -Backup-File $WindowsAgentConfigFile -Remove-Item $WindowsAgentConfigFile -Force -ConvertFrom-Base64String -Base64String $WindowsAgentConfigBase64 -Path $WindowsAgentConfigFile -Exec sc.exe 'config','"Keero Agent"','start=','delayed-auto' -Write-Log "Service has been updated." - -Write-Log "Renaming computer ..." -Rename-Computer -NewName $NewComputerName | Out-Null -Write-Log "New name assigned, restart required." -$RestartRequired = $true - - -Write-Log 'All done!' -if ( $RestartRequired ) { - Write-Log "Restarting computer ..." - Restart-Computer -Force -} -else { - Start-Service 'Keero Agent' -} diff --git a/conductor/data/templates/agent-config/Default.template b/conductor/data/templates/agent-config/Default.template deleted file mode 100644 index 36287273..00000000 --- a/conductor/data/templates/agent-config/Default.template +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<configuration> - <configSections> - <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog"/> - </configSections> - <startup> - <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> - </startup> - <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> - <targets> - <target name="file" xsi:type="File" fileName="${basedir}/log.txt" - layout="${date} ${level}: &lt;${logger:shortName=true}&gt; ${message} ${exception:format=tostring}"/> - </targets> - - <rules> - <logger name="*" minlevel="Debug" writeTo="file" /> - </rules> - </nlog> - <appSettings> - <add key="rabbitmq.host" value="%RABBITMQ_HOST%"/> - <add key="rabbitmq.user" value="%RABBITMQ_USER%"/> - <add key="rabbitmq.password" value="%RABBITMQ_PASSWORD%"/> - <add key="rabbitmq.vhost" value="%RABBITMQ_VHOST%"/> - <add key="rabbitmq.inputQueue" value="%RABBITMQ_INPUT_QUEUE%"/> - <add key="rabbitmq.resultExchange" value=""/> - <add key="rabbitmq.resultRoutingKey" value="%RESULT_QUEUE%"/> - <add key="rabbitmq.durableMessages" value="true"/> - - </appSettings> -</configuration> \ No newline at end of file diff --git a/conductor/data/templates/agent/AskDnsIp.template b/conductor/data/templates/agent/AskDnsIp.template deleted file mode 100644 index a9f6ee38..00000000 --- a/conductor/data/templates/agent/AskDnsIp.template +++ /dev/null @@ -1,12 +0,0 @@ -{ - "Scripts": [ - "ZnVuY3Rpb24gR2V0LURuc0xpc3RlbmluZ0lwQWRkcmVzcyB7DQogICAgSW1wb3J0LU1vZHVsZSBEbnNTZXJ2ZXINCiAgICAoR2V0LUROU1NlcnZlciAtQ29tcHV0ZXJOYW1lIGxvY2FsaG9zdCkuU2VydmVyU2V0dGluZy5MaXN0ZW5pbmdJcEFkZHJlc3MgfA0KICAgICAgICBXaGVyZS1PYmplY3QgeyAkXyAtbWF0Y2ggIlxkezEsM31cLlxkezEsM31cLlxkezEsM31cLlxkezEsM30iIH0NCn0NCg==" - ], - "Commands": [ - { - "Name": "Get-DnsListeningIpAddress", - "Arguments": {} - } - ], - "RebootOnCompletion": 0 -} \ No newline at end of file diff --git a/conductor/data/templates/agent/CreatePrimaryDC.template b/conductor/data/templates/agent/CreatePrimaryDC.template deleted file mode 100644 index f3b68679..00000000 --- a/conductor/data/templates/agent/CreatePrimaryDC.template +++ /dev/null @@ -1,21 +0,0 @@ -{ - "Scripts": [ - "RnVuY3Rpb24gU2V0LUxvY2FsVXNlclBhc3N3b3JkIHsKICAgIHBhcmFtICgKICAgICAgICBbU3RyaW5nXSAkVXNlck5hbWUsCiAgICAgICAgW1N0cmluZ10gJFBhc3N3b3JkLAogICAgICAgIFtTd2l0Y2hdICRGb3JjZQogICAgKQogICAgCiAgICB0cmFwIHsgU3RvcC1FeGVjdXRpb24gJF8gfQogICAgCiAgICBpZiAoKEdldC1XbWlPYmplY3QgV2luMzJfVXNlckFjY291bnQgLUZpbHRlciAiTG9jYWxBY2NvdW50ID0gJ1RydWUnIEFORCBOYW1lPSckVXNlck5hbWUnIikgLWVxICRudWxsKSB7CiAgICAgICAgdGhyb3cgIlVuYWJsZSB0byBmaW5kIGxvY2FsIHVzZXIgYWNjb3VudCAnJFVzZXJOYW1lJyIKICAgIH0KICAgIAogICAgaWYgKCRGb3JjZSkgewogICAgICAgIFdyaXRlLUxvZyAiQ2hhbmdpbmcgcGFzc3dvcmQgZm9yIHVzZXIgJyRVc2VyTmFtZScgdG8gJyoqKioqJyIgIyA6KQogICAgICAgIChbQURTSV0gIldpbk5UOi8vLi8kVXNlck5hbWUiKS5TZXRQYXNzd29yZCgkUGFzc3dvcmQpCiAgICB9CiAgICBlbHNlIHsKICAgICAgICBXcml0ZS1Mb2dXYXJuaW5nICJZb3UgYXJlIHRyeWluZyB0byBjaGFuZ2UgcGFzc3dvcmQgZm9yIHVzZXIgJyRVc2VyTmFtZScuIFRvIGRvIHRoaXMgcGxlYXNlIHJ1biB0aGUgY29tbWFuZCBhZ2FpbiB3aXRoIC1Gb3JjZSBwYXJhbWV0ZXIuIgogICAgICAgICRVc2VyQWNjb3VudAogICAgfQp9CgoKCkZ1bmN0aW9uIEluc3RhbGwtUm9sZVByaW1hcnlEb21haW5Db250cm9sbGVyCnsKPCMKLlNZTk9QU0lTCkNvbmZpZ3VyZSBub2RlJ3MgbmV0d29yayBhZGFwdGVycy4KQ3JlYXRlIGZpcnN0IGRvbWFpbiBjb250cm9sbGVyIGluIHRoZSBmb3Jlc3QuCgouRVhBTVBMRQpQUz4gSW5zdGFsbC1Sb2xlUHJpbWFyeURvbWFpbkNvbnRyb2xsZXIgLURvbWFpbk5hbWUgYWNtZS5sb2NhbCAtU2FmZU1vZGVQYXNzd29yZCAiUEBzc3cwcmQiCgpJbnN0YWxsIEROUyBhbmQgQUREUywgY3JlYXRlIGZvcmVzdCBhbmQgZG9tYWluICdhY21lLmxvY2FsJy4KU2V0IERDIHJlY292ZXJ5IG1vZGUgcGFzc3dvcmQgdG8gJ1BAc3N3MHJkJy4KIz4KCQoJcGFyYW0KCSgKCQlbU3RyaW5nXQoJCSMgTmV3IGRvbWFpbiBuYW1lLgoJCSREb21haW5OYW1lLAoJCQoJCVtTdHJpbmddCgkJIyBEb21haW4gY29udHJvbGxlciByZWNvdmVyeSBtb2RlIHBhc3N3b3JkLgoJCSRTYWZlTW9kZVBhc3N3b3JkCgkpCgoJdHJhcCB7IFN0b3AtRXhlY3V0aW9uICRfIH0KCiAgICAgICAgIyBBZGQgcmVxdWlyZWQgd2luZG93cyBmZWF0dXJlcwoJQWRkLVdpbmRvd3NGZWF0dXJlV3JhcHBlciBgCgkJLU5hbWUgIkROUyIsIkFELURvbWFpbi1TZXJ2aWNlcyIsIlJTQVQtREZTLU1nbXQtQ29uIiBgCgkJLUluY2x1ZGVNYW5hZ2VtZW50VG9vbHMgYAogICAgICAgIC1Ob3RpZnlSZXN0YXJ0CgoKCVdyaXRlLUxvZyAiQ3JlYXRpbmcgZmlyc3QgZG9tYWluIGNvbnRyb2xsZXIgLi4uIgoJCQoJJFNNQVAgPSBDb252ZXJ0VG8tU2VjdXJlU3RyaW5nIC1TdHJpbmcgJFNhZmVNb2RlUGFzc3dvcmQgLUFzUGxhaW5UZXh0IC1Gb3JjZQoJCQoJSW5zdGFsbC1BRERTRm9yZXN0IGAKCQktRG9tYWluTmFtZSAkRG9tYWluTmFtZSBgCgkJLVNhZmVNb2RlQWRtaW5pc3RyYXRvclBhc3N3b3JkICRTTUFQIGAKCQktRG9tYWluTW9kZSBEZWZhdWx0IGAKCQktRm9yZXN0TW9kZSBEZWZhdWx0IGAKCQktTm9SZWJvb3RPbkNvbXBsZXRpb24gYAoJCS1Gb3JjZSBgCgkJLUVycm9yQWN0aW9uIFN0b3AgfCBPdXQtTnVsbAoKCVdyaXRlLUxvZyAiV2FpdGluZyBmb3IgcmVib290IC4uLiIJCQojCVN0b3AtRXhlY3V0aW9uIC1FeGl0Q29kZSAzMDEwIC1FeGl0U3RyaW5nICJDb21wdXRlciBtdXN0IGJlIHJlc3RhcnRlZCB0byBmaW5pc2ggZG9tYWluIGNvbnRyb2xsZXIgcHJvbW90aW9uLiIKIwlXcml0ZS1Mb2cgIlJlc3RhcmluZyBjb21wdXRlciAuLi4iCiMJUmVzdGFydC1Db21wdXRlciAtRm9yY2UKfQo=" - ], - "Commands": [ - { - "Name": "Import-Module", - "Arguments": { - "Name": "CoreFunctions" - } - }, - { - "Name": "Install-RolePrimaryDomainController", - "Arguments": { - "DomainName": "$domain", - "SafeModePassword": "$recoveryPassword" - } - } - ], - "RebootOnCompletion": 1 -} \ No newline at end of file diff --git a/conductor/data/templates/agent/CreateSecondaryDC.template b/conductor/data/templates/agent/CreateSecondaryDC.template deleted file mode 100644 index a5ad7f45..00000000 --- a/conductor/data/templates/agent/CreateSecondaryDC.template +++ /dev/null @@ -1,23 +0,0 @@ -{ - "Scripts": [ - "RnVuY3Rpb24gSW5zdGFsbC1Sb2xlU2Vjb25kYXJ5RG9tYWluQ29udHJvbGxlcg0Kew0KPCMNCi5TWU5PUFNJUw0KSW5zdGFsbCBhZGRpdGlvbmFsIChzZWNvbmRhcnkpIGRvbWFpbiBjb250cm9sbGVyLg0KDQojPg0KCXBhcmFtDQoJKA0KCQlbU3RyaW5nXQ0KCQkjIERvbWFpbiBuYW1lIHRvIGpvaW4gdG8uDQoJCSREb21haW5OYW1lLA0KCQkNCgkJW1N0cmluZ10NCgkJIyBEb21haW4gdXNlciB3aG8gaXMgYWxsb3dlZCB0byBqb2luIGNvbXB1dGVyIHRvIGRvbWFpbi4NCgkJJFVzZXJOYW1lLA0KCQkNCgkJW1N0cmluZ10NCgkJIyBVc2VyJ3MgcGFzc3dvcmQuDQoJCSRQYXNzd29yZCwNCgkJDQoJCVtTdHJpbmddDQoJCSMgRG9tYWluIGNvbnRyb2xsZXIgcmVjb3ZlcnkgbW9kZSBwYXNzd29yZC4NCgkJJFNhZmVNb2RlUGFzc3dvcmQNCgkpDQoNCgl0cmFwIHsgU3RvcC1FeGVjdXRpb24gJF8gfQ0KCQ0KCSRDcmVkZW50aWFsID0gTmV3LUNyZWRlbnRpYWwgLVVzZXJOYW1lICIkRG9tYWluTmFtZVwkVXNlck5hbWUiIC1QYXNzd29yZCAkUGFzc3dvcmQNCgkJDQoJIyBBZGQgcmVxdWlyZWQgd2luZG93cyBmZWF0dXJlcw0KCUFkZC1XaW5kb3dzRmVhdHVyZVdyYXBwZXIgYA0KCQktTmFtZSAiRE5TIiwiQUQtRG9tYWluLVNlcnZpY2VzIiwiUlNBVC1ERlMtTWdtdC1Db24iIGANCgkJLUluY2x1ZGVNYW5hZ2VtZW50VG9vbHMgYA0KICAgICAgICAgICAgICAgIC1Ob3RpZnlSZXN0YXJ0DQoJCQ0KCQ0KICAgICAgICBXcml0ZS1Mb2cgIkFkZGluZyBzZWNvbmRhcnkgZG9tYWluIGNvbnRyb2xsZXIgLi4uIg0KICAgIA0KCSRTTUFQID0gQ29udmVydFRvLVNlY3VyZVN0cmluZyAtU3RyaW5nICRTYWZlTW9kZVBhc3N3b3JkIC1Bc1BsYWluVGV4dCAtRm9yY2UNCg0KCUluc3RhbGwtQUREU0RvbWFpbkNvbnRyb2xsZXIgYA0KCQktRG9tYWluTmFtZSAkRG9tYWluTmFtZSBgDQoJCS1TYWZlTW9kZUFkbWluaXN0cmF0b3JQYXNzd29yZCAkU01BUCBgDQoJCS1DcmVkZW50aWFsICRDcmVkZW50aWFsIGANCgkJLU5vUmVib290T25Db21wbGV0aW9uIGANCgkJLUZvcmNlIGANCgkJLUVycm9yQWN0aW9uIFN0b3AgfCBPdXQtTnVsbA0KDQoJV3JpdGUtTG9nICJXYWl0aW5nIGZvciByZXN0YXJ0IC4uLiINCiMJU3RvcC1FeGVjdXRpb24gLUV4aXRDb2RlIDMwMTAgLUV4aXRTdHJpbmcgIkNvbXB1dGVyIG11c3QgYmUgcmVzdGFydGVkIHRvIGZpbmlzaCBkb21haW4gY29udHJvbGxlciBwcm9tb3Rpb24uIg0KIwlXcml0ZS1Mb2cgIlJlc3RhcnRpbmcgY29tcHV0ZXIgLi4uIg0KIwlSZXN0YXJ0LUNvbXB1dGVyIC1Gb3JjZQ0KfQ0K" - ], - "Commands": [ - { - "Name": "Import-Module", - "Arguments": { - "Name": "CoreFunctions" - } - }, - { - "Name": "Install-RoleSecondaryDomainController", - "Arguments": { - "DomainName": "$domain", - "UserName": "Administrator", - "Password": "$domainPassword", - "SafeModePassword": "$recoveryPassword" - } - } - ], - "RebootOnCompletion": 1 -} \ No newline at end of file diff --git a/conductor/data/templates/agent/InstallIIS.template b/conductor/data/templates/agent/InstallIIS.template deleted file mode 100644 index baeaec15..00000000 --- a/conductor/data/templates/agent/InstallIIS.template +++ /dev/null @@ -1,12 +0,0 @@ -{ - "Scripts": [ - "ZnVuY3Rpb24gSW5zdGFsbC1XZWJTZXJ2ZXIgew0KICAgIEltcG9ydC1Nb2R1bGUgU2VydmVyTWFuYWdlcg0KICAgIEluc3RhbGwtV2luZG93c0ZlYXR1cmUgV2ViLVNlcnZlciAtSW5jbHVkZU1hbmFnZW1lbnRUb29scw0KfQ0K" - ], - "Commands": [ - { - "Name": "Install-WebServer", - "Arguments": {} - } - ], - "RebootOnCompletion": 0 -} \ No newline at end of file diff --git a/conductor/data/templates/agent/JoinDomain.template b/conductor/data/templates/agent/JoinDomain.template deleted file mode 100644 index 85e4b9ca..00000000 --- a/conductor/data/templates/agent/JoinDomain.template +++ /dev/null @@ -1,27 +0,0 @@ -{ - "Scripts": [], - "Commands": [ - { - "Name": "Import-Module", - "Arguments": { - "Name": "CoreFunctions" - } - }, - { - "Name": "Set-NetworkAdapterConfiguration", - "Arguments": { - "FirstAvailable": true, - "DNSServer": "$dnsIp" - } - }, - { - "Name": "Join-Domain", - "Arguments": { - "DomainName": "$domain", - "Username": "Administrator", - "Password": "$domainPassword" - } - } - ], - "RebootOnCompletion": 1 -} \ No newline at end of file diff --git a/conductor/data/templates/agent/SetPassword.template b/conductor/data/templates/agent/SetPassword.template deleted file mode 100644 index 1cc9dcc9..00000000 --- a/conductor/data/templates/agent/SetPassword.template +++ /dev/null @@ -1,22 +0,0 @@ -{ - "Scripts": [ - "RnVuY3Rpb24gU2V0LUxvY2FsVXNlclBhc3N3b3JkIHsNCiAgICBwYXJhbSAoDQogICAgICAgIFtTdHJpbmddICRVc2VyTmFtZSwNCiAgICAgICAgW1N0cmluZ10gJFBhc3N3b3JkLA0KICAgICAgICBbU3dpdGNoXSAkRm9yY2UNCiAgICApDQogICAgDQogICAgdHJhcCB7IFN0b3AtRXhlY3V0aW9uICRfIH0NCiAgICANCiAgICBpZiAoKEdldC1XbWlPYmplY3QgV2luMzJfVXNlckFjY291bnQgLUZpbHRlciAiTG9jYWxBY2NvdW50ID0gJ1RydWUnIEFORCBOYW1lPSckVXNlck5hbWUnIikgLWVxICRudWxsKSB7DQogICAgICAgIHRocm93ICJVbmFibGUgdG8gZmluZCBsb2NhbCB1c2VyIGFjY291bnQgJyRVc2VyTmFtZSciDQogICAgfQ0KICAgIA0KICAgIGlmICgkRm9yY2UpIHsNCiAgICAgICAgV3JpdGUtTG9nICJDaGFuZ2luZyBwYXNzd29yZCBmb3IgdXNlciAnJFVzZXJOYW1lJyB0byAnKioqKionIiAjIDopDQogICAgICAgIChbQURTSV0gIldpbk5UOi8vLi8kVXNlck5hbWUiKS5TZXRQYXNzd29yZCgkUGFzc3dvcmQpDQogICAgfQ0KICAgIGVsc2Ugew0KICAgICAgICBXcml0ZS1Mb2dXYXJuaW5nICJZb3UgYXJlIHRyeWluZyB0byBjaGFuZ2UgcGFzc3dvcmQgZm9yIHVzZXIgJyRVc2VyTmFtZScuIFRvIGRvIHRoaXMgcGxlYXNlIHJ1biB0aGUgY29tbWFuZCBhZ2FpbiB3aXRoIC1Gb3JjZSBwYXJhbWV0ZXIuIg0KICAgICAgICAkVXNlckFjY291bnQNCiAgICB9DQp9DQoNCg0KDQpGdW5jdGlvbiBJbnN0YWxsLVJvbGVQcmltYXJ5RG9tYWluQ29udHJvbGxlcg0Kew0KPCMNCi5TWU5PUFNJUw0KQ29uZmlndXJlIG5vZGUncyBuZXR3b3JrIGFkYXB0ZXJzLg0KQ3JlYXRlIGZpcnN0IGRvbWFpbiBjb250cm9sbGVyIGluIHRoZSBmb3Jlc3QuDQoNCi5FWEFNUExFDQpQUz4gSW5zdGFsbC1Sb2xlUHJpbWFyeURvbWFpbkNvbnRyb2xsZXIgLURvbWFpbk5hbWUgYWNtZS5sb2NhbCAtU2FmZU1vZGVQYXNzd29yZCAiUEBzc3cwcmQiDQoNCkluc3RhbGwgRE5TIGFuZCBBRERTLCBjcmVhdGUgZm9yZXN0IGFuZCBkb21haW4gJ2FjbWUubG9jYWwnLg0KU2V0IERDIHJlY292ZXJ5IG1vZGUgcGFzc3dvcmQgdG8gJ1BAc3N3MHJkJy4NCiM+DQoJDQoJcGFyYW0NCgkoDQoJCVtTdHJpbmddDQoJCSMgTmV3IGRvbWFpbiBuYW1lLg0KCQkkRG9tYWluTmFtZSwNCgkJDQoJCVtTdHJpbmddDQoJCSMgRG9tYWluIGNvbnRyb2xsZXIgcmVjb3ZlcnkgbW9kZSBwYXNzd29yZC4NCgkJJFNhZmVNb2RlUGFzc3dvcmQNCgkpDQoNCgl0cmFwIHsgU3RvcC1FeGVjdXRpb24gJF8gfQ0KDQogICAgICAgICMgQWRkIHJlcXVpcmVkIHdpbmRvd3MgZmVhdHVyZXMNCglBZGQtV2luZG93c0ZlYXR1cmVXcmFwcGVyIGANCgkJLU5hbWUgIkROUyIsIkFELURvbWFpbi1TZXJ2aWNlcyIsIlJTQVQtREZTLU1nbXQtQ29uIiBgDQoJCS1JbmNsdWRlTWFuYWdlbWVudFRvb2xzIGANCiAgICAgICAgLU5vdGlmeVJlc3RhcnQNCg0KDQoJV3JpdGUtTG9nICJDcmVhdGluZyBmaXJzdCBkb21haW4gY29udHJvbGxlciAuLi4iDQoJCQ0KCSRTTUFQID0gQ29udmVydFRvLVNlY3VyZVN0cmluZyAtU3RyaW5nICRTYWZlTW9kZVBhc3N3b3JkIC1Bc1BsYWluVGV4dCAtRm9yY2UNCgkJDQoJSW5zdGFsbC1BRERTRm9yZXN0IGANCgkJLURvbWFpbk5hbWUgJERvbWFpbk5hbWUgYA0KCQktU2FmZU1vZGVBZG1pbmlzdHJhdG9yUGFzc3dvcmQgJFNNQVAgYA0KCQktRG9tYWluTW9kZSBEZWZhdWx0IGANCgkJLUZvcmVzdE1vZGUgRGVmYXVsdCBgDQoJCS1Ob1JlYm9vdE9uQ29tcGxldGlvbiBgDQoJCS1Gb3JjZSBgDQoJCS1FcnJvckFjdGlvbiBTdG9wIHwgT3V0LU51bGwNCg0KCVdyaXRlLUhvc3QgIldhaXRpbmcgZm9yIHJlYm9vdCAuLi4iCQkNCiMJU3RvcC1FeGVjdXRpb24gLUV4aXRDb2RlIDMwMTAgLUV4aXRTdHJpbmcgIkNvbXB1dGVyIG11c3QgYmUgcmVzdGFydGVkIHRvIGZpbmlzaCBkb21haW4gY29udHJvbGxlciBwcm9tb3Rpb24uIg0KIwlXcml0ZS1Mb2cgIlJlc3RhcmluZyBjb21wdXRlciAuLi4iDQojCVJlc3RhcnQtQ29tcHV0ZXIgLUZvcmNlDQp9DQo=" - ], - "Commands": [ - { - "Name": "Import-Module", - "Arguments": { - "Name": "CoreFunctions" - } - }, - { - "Name": "Set-LocalUserPassword", - "Arguments": { - "UserName": "Administrator", - "Password": "$adminPassword", - "Force": true - } - } - ], - "RebootOnCompletion": 0 -} \ No newline at end of file diff --git a/conductor/data/templates/cf/Windows.template b/conductor/data/templates/cf/Windows.template deleted file mode 100644 index e14069ff..00000000 --- a/conductor/data/templates/cf/Windows.template +++ /dev/null @@ -1,62 +0,0 @@ -{ - "AWSTemplateFormatVersion" : "2010-09-09", - - "Description" : "", - - "Parameters" : { - "KeyName" : { - "Description" : "Name of an existing Amazon EC2 key pair for RDP access", - "Type" : "String", - "Default" : "keero_key" - }, - "InstanceType" : { - "Description" : "Amazon EC2 instance type", - "Type" : "String", - "Default" : "m1.medium", - "AllowedValues" : [ "m1.small", "m1.medium", "m1.large" ] - }, - "ImageName" : { - "Description" : "Image name", - "Type" : "String", - "Default" : "ws-2012-full-agent", - "AllowedValues" : [ "ws-2012-full", "ws-2012-core", "ws-2012-full-agent" ] - } - }, - - "Resources" : { - "IAMUser" : { - "Type" : "AWS::IAM::User", - "Properties" : { - "Path": "/", - "Policies": [{ - "PolicyName": "root", - "PolicyDocument": { "Statement":[{ - "Effect": "Allow", - "Action": "CloudFormation:DescribeStackResource", - "Resource": "*" - }]} - }] - } - }, - - "IAMUserAccessKey" : { - "Type" : "AWS::IAM::AccessKey", - "Properties" : { - "UserName" : {"Ref": "IAMUser"} - } - }, - - "$instanceName": { - "Type" : "AWS::EC2::Instance", - "Properties": { - "InstanceType" : { "Ref" : "InstanceType" }, - "ImageId" : { "Ref" : "ImageName" }, - "KeyName" : { "Ref" : "KeyName" }, - "UserData": "$userData" - } - } - }, - - "Outputs" : { - } -} \ No newline at end of file diff --git a/conductor/data/workflows/AD.xml b/conductor/data/workflows/AD.xml deleted file mode 100644 index 0433e4d0..00000000 --- a/conductor/data/workflows/AD.xml +++ /dev/null @@ -1,218 +0,0 @@ -<workflow> - <rule match="$.services.activeDirectories[?(@.domain)].units[?(not @.isMaster)]"> - <set path="domain"> - <select path="::domain"/> - </set> - </rule> - - <rule match="$.services.activeDirectories[*].units[?(@.state.hostname and not @.state.instanceName)]"> - <report entity="unit"> - <parameter name="id"><select path="id"/></parameter> - <parameter name="text">Creating instance <select path="name"/></parameter> - </report> - <update-cf-stack template="Windows"> - <parameter name="mappings"> - <map> - <mapping name="instanceName"><select path="::name"/>-<select path="name"/></mapping> - <mapping name="userData"> - <prepare-user-data> - <parameter name="hostname"><select path="state.hostname"/></parameter> - <parameter name="unit"><select path="name"/></parameter> - <parameter name="service"><select path="::id"/></parameter> - </prepare-user-data> - </mapping> - </map> - </parameter> - <parameter name="arguments"> - <map> - <argument name="KeyName">keero-keys</argument> - <argument name="InstanceType">m1.medium</argument> - <argument name="ImageName">ws-2012-full</argument> - </map> - </parameter> - - <success> - <set path="state.instanceName"><select path="name"/></set> - <report entity="unit"> - <parameter name="id"><select path="id"/></parameter> - <parameter name="text">Instance <select path="name"/> created</parameter> - </report> - </success> - </update-cf-stack> - </rule> - - <rule match="$.services.activeDirectories[*].units[?(@.state.instanceName and @.adminPassword and @.adminPassword != @.state.adminPassword)]"> - <send-command template="SetPassword"> - <parameter name="host"> - <select path="name"/> - </parameter> - <parameter name="service"> - <select path="::id"/> - </parameter> - <parameter name="mappings"> - <map> - <mapping name="adminPassword"> - <select path="adminPassword"/> - </mapping> - </map> - </parameter> - <success> - <set path="state.adminPassword"> - <select path="adminPassword"/> - </set> - </success> - </send-command> - </rule> - - <rule match="$.services.activeDirectories[?(@.adminPassword and @.adminPassword != @.state.domainAdminPassword)].units[?(@.state.instanceName and @.isMaster)]"> - <send-command template="SetPassword"> - <parameter name="host"> - <select path="name"/> - </parameter> - <parameter name="service"> - <select path="::id"/> - </parameter> - <parameter name="mappings"> - <map> - <mapping name="adminPassword"> - <select path="::adminPassword"/> - </mapping> - </map> - </parameter> - <success> - <set path="::state.domainAdminPassword"> - <select path="::adminPassword"/> - </set> - </success> - </send-command> - </rule> - - <rule match="$.services.activeDirectories[?(@.state.primaryDc is None)].units[?(@.state.instanceName and @.isMaster)]"> - <report entity="unit"> - <parameter name="id"><select path="id"/></parameter> - <parameter name="text">Creating Primary Domain Controller on unit <select path="name"/></parameter> - </report> - <send-command template="CreatePrimaryDC"> - <parameter name="host"> - <select path="name"/> - </parameter> - <parameter name="service"> - <select path="::id"/> - </parameter> - <parameter name="mappings"> - <map> - <mapping name="domain"> - <select path="::domain"/> - </mapping> - <mapping name="recoveryPassword"> - <select path="recoveryPassword"/> - </mapping> - </map> - </parameter> - <success> - <set path="::state.primaryDc"><select path="name"/></set> - <report entity="unit"> - <parameter name="id"><select path="id"/></parameter> - <parameter name="text">Primary Domain Controller created</parameter> - </report> - </success> - </send-command> - </rule> - - <rule match="$.services.activeDirectories[?(@.state.primaryDc and not @.state.primaryDcIp)].units[?(@.state.instanceName and @.isMaster)]"> - <send-command template="AskDnsIp" result="ip"> - <parameter name="host"> - <select path="name"/> - </parameter> - <parameter name="service"> - <select path="::id"/> - </parameter> - <success> - <set path="::state.primaryDcIp"> - <select source="ip" path="0.Result.0"/> - </set> - </success> - </send-command> - </rule> - - <rule match="$..units[?(@.state.instanceName and @.domain and @.domain != @.state.domain)]"> - <set path="#unit"> - <select/> - </set> - <set path="#service"> - <select path="::"/> - </set> - <rule> - <parameter name="match">/$.services.activeDirectories[?(@.domain == '<select path="domain"/>' and @.state.primaryDcIp)]</parameter> - - <send-command template="JoinDomain"> - <parameter name="host"> - <select path="name" source="unit"/> - </parameter> - <parameter name="service"> - <select path="id" source="service"/> - </parameter> - <parameter name="mappings"> - <map> - <mapping name="domain"> - <select path="domain"/> - </mapping> - <mapping name="domainPassword"> - <select path="adminPassword"/> - </mapping> - <mapping name="dnsIp"> - <select path="state.primaryDcIp"/> - </mapping> - </map> - </parameter> - - <success> - <set path="state.domain" target="unit"> - <select path="domain"/> - </set> - <report entity="unit"> - <parameter name="id"><select path="id" source="unit"/></parameter> - <parameter name="text">Unit <select path="name" source="unit"/> has joined domain <select path="domain"/></parameter> - </report> - </success> - </send-command> - </rule> - </rule> - - - <rule match="$.services.activeDirectories[*].units[?(@.state.domain and not @.isMaster and not @.state.installed)]"> - <report entity="unit"> - <parameter name="id"><select path="id"/></parameter> - <parameter name="text">Creating Secondary Domain Controller on unit <select path="name"/></parameter> - </report> - <send-command template="CreateSecondaryDC"> - <parameter name="host"> - <select path="name"/> - </parameter> - <parameter name="service"> - <select path="::id"/> - </parameter> - <parameter name="mappings"> - <map> - <mapping name="recoveryPassword"> - <select path="recoveryPassword"/> - </mapping> - <mapping name="domainPassword"> - <select path="::adminPassword"/> - </mapping> - </map> - </parameter> - <success> - <set path="state.installed"><true/></set> - <report entity="unit"> - <parameter name="id"><select path="id"/></parameter> - <parameter name="text">Secondary Domain Controller created</parameter> - </report> - <report entity="service"> - <parameter name="id"><select path="::id"/></parameter> - <parameter name="text">Domain <select path="::domain"/> created</parameter> - </report> - </success> - </send-command> - </rule> -</workflow> \ No newline at end of file diff --git a/conductor/data/workflows/Common.xml b/conductor/data/workflows/Common.xml deleted file mode 100644 index 01d13259..00000000 --- a/conductor/data/workflows/Common.xml +++ /dev/null @@ -1,19 +0,0 @@ -<workflow> - - <rule match="$.services[*][*].units[?(@.state.hostname is None)]"> - <set path="state.hostname"><generate-hostname/></set> - </rule> - - <rule match="$[?(not @.state.deleted)]"> - <rule match="$.services[*][*].units[*]"> - <empty> - <delete-cf-stack> - <success> - <set path="/state.deleted"><true/></set> - </success> - </delete-cf-stack> - </empty> - </rule> - </rule> - -</workflow> \ No newline at end of file diff --git a/conductor/data/workflows/IIS.xml b/conductor/data/workflows/IIS.xml deleted file mode 100644 index 136358b4..00000000 --- a/conductor/data/workflows/IIS.xml +++ /dev/null @@ -1,65 +0,0 @@ -<workflow> - <rule match="$.services.webServers[?(@.domain)].units[*]"> - <set path="domain"> - <select path="::domain"/> - </set> - </rule> - - <rule match="$.services.webServers[*].units[?(@.state.hostname and not @.state.instanceName)]"> - <report entity="unit"> - <parameter name="id"><select path="id"/></parameter> - <parameter name="text">Creating instance <select path="name"/></parameter> - </report> - <update-cf-stack template="Windows"> - <parameter name="mappings"> - <map> - <mapping name="instanceName"><select path="::name"/>-<select path="name"/></mapping> - <mapping name="userData"> - <prepare-user-data> - <parameter name="hostname"><select path="state.hostname"/></parameter> - <parameter name="unit"><select path="name"/></parameter> - <parameter name="service"><select path="::id"/></parameter> - </prepare-user-data> - </mapping> - </map> - </parameter> - <parameter name="arguments"> - <map> - <argument name="KeyName">keero-keys</argument> - <argument name="InstanceType">m1.medium</argument> - <argument name="ImageName">ws-2012-full</argument> - </map> - </parameter> - - <success> - <set path="state.instanceName"><select path="name"/></set> - <report entity="unit"> - <parameter name="id"><select path="id"/></parameter> - <parameter name="text">Instance <select path="name"/> created</parameter> - </report> - </success> - </update-cf-stack> - </rule> - - <rule match="$.services.webServers[*].units[?(@.state.instanceName and not @.state.iisInstalled)]"> - <report entity="unit"> - <parameter name="id"><select path="id"/></parameter> - <parameter name="text">Creating IIS Web Server on unit <select path="name"/></parameter> - </report> - <send-command template="InstallIIS"> - <parameter name="host"> - <select path="name"/> - </parameter> - <parameter name="service"> - <select path="::id"/> - </parameter> - <success> - <set path="state.iisInstalled"><true/></set> - <report entity="unit"> - <parameter name="id"><select path="id"/></parameter> - <parameter name="text">IIS <select path="name"/> has started</parameter> - </report> - </success> - </send-command> - </rule> -</workflow> \ No newline at end of file diff --git a/conductor/doc/source/_static/basic.css b/conductor/doc/source/_static/basic.css deleted file mode 100644 index d909ce37..00000000 --- a/conductor/doc/source/_static/basic.css +++ /dev/null @@ -1,416 +0,0 @@ -/** - * Sphinx stylesheet -- basic theme - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -/* -- main layout ----------------------------------------------------------- */ - -div.clearer { - clear: both; -} - -/* -- relbar ---------------------------------------------------------------- */ - -div.related { - width: 100%; - font-size: 90%; -} - -div.related h3 { - display: none; -} - -div.related ul { - margin: 0; - padding: 0 0 0 10px; - list-style: none; -} - -div.related li { - display: inline; -} - -div.related li.right { - float: right; - margin-right: 5px; -} - -/* -- sidebar --------------------------------------------------------------- */ - -div.sphinxsidebarwrapper { - padding: 10px 5px 0 10px; -} - -div.sphinxsidebar { - float: left; - width: 230px; - margin-left: -100%; - font-size: 90%; -} - -div.sphinxsidebar ul { - list-style: none; -} - -div.sphinxsidebar ul ul, -div.sphinxsidebar ul.want-points { - margin-left: 20px; - list-style: square; -} - -div.sphinxsidebar ul ul { - margin-top: 0; - margin-bottom: 0; -} - -div.sphinxsidebar form { - margin-top: 10px; -} - -div.sphinxsidebar input { - border: 1px solid #98dbcc; - font-family: sans-serif; - font-size: 1em; -} - -img { - border: 0; -} - -/* -- search page ----------------------------------------------------------- */ - -ul.search { - margin: 10px 0 0 20px; - padding: 0; -} - -ul.search li { - padding: 5px 0 5px 20px; - background-image: url(file.png); - background-repeat: no-repeat; - background-position: 0 7px; -} - -ul.search li a { - font-weight: bold; -} - -ul.search li div.context { - color: #888; - margin: 2px 0 0 30px; - text-align: left; -} - -ul.keywordmatches li.goodmatch a { - font-weight: bold; -} - -/* -- index page ------------------------------------------------------------ */ - -table.contentstable { - width: 90%; -} - -table.contentstable p.biglink { - line-height: 150%; -} - -a.biglink { - font-size: 1.3em; -} - -span.linkdescr { - font-style: italic; - padding-top: 5px; - font-size: 90%; -} - -/* -- general index --------------------------------------------------------- */ - -table.indextable td { - text-align: left; - vertical-align: top; -} - -table.indextable dl, table.indextable dd { - margin-top: 0; - margin-bottom: 0; -} - -table.indextable tr.pcap { - height: 10px; -} - -table.indextable tr.cap { - margin-top: 10px; - background-color: #f2f2f2; -} - -img.toggler { - margin-right: 3px; - margin-top: 3px; - cursor: pointer; -} - -/* -- general body styles --------------------------------------------------- */ - -a.headerlink { - visibility: hidden; -} - -h1:hover > a.headerlink, -h2:hover > a.headerlink, -h3:hover > a.headerlink, -h4:hover > a.headerlink, -h5:hover > a.headerlink, -h6:hover > a.headerlink, -dt:hover > a.headerlink { - visibility: visible; -} - -div.body p.caption { - text-align: inherit; -} - -div.body td { - text-align: left; -} - -.field-list ul { - padding-left: 1em; -} - -.first { -} - -p.rubric { - margin-top: 30px; - font-weight: bold; -} - -/* -- sidebars -------------------------------------------------------------- */ - -div.sidebar { - margin: 0 0 0.5em 1em; - border: 1px solid #ddb; - padding: 7px 7px 0 7px; - background-color: #ffe; - width: 40%; - float: right; -} - -p.sidebar-title { - font-weight: bold; -} - -/* -- topics ---------------------------------------------------------------- */ - -div.topic { - border: 1px solid #ccc; - padding: 7px 7px 0 7px; - margin: 10px 0 10px 0; -} - -p.topic-title { - font-size: 1.1em; - font-weight: bold; - margin-top: 10px; -} - -/* -- admonitions ----------------------------------------------------------- */ - -div.admonition { - margin-top: 10px; - margin-bottom: 10px; - padding: 7px; -} - -div.admonition dt { - font-weight: bold; -} - -div.admonition dl { - margin-bottom: 0; -} - -p.admonition-title { - margin: 0px 10px 5px 0px; - font-weight: bold; -} - -div.body p.centered { - text-align: center; - margin-top: 25px; -} - -/* -- tables ---------------------------------------------------------------- */ - -table.docutils { - border: 0; - border-collapse: collapse; -} - -table.docutils td, table.docutils th { - padding: 1px 8px 1px 0; - border-top: 0; - border-left: 0; - border-right: 0; - border-bottom: 1px solid #aaa; -} - -table.field-list td, table.field-list th { - border: 0 !important; -} - -table.footnote td, table.footnote th { - border: 0 !important; -} - -th { - text-align: left; - padding-right: 5px; -} - -/* -- other body styles ----------------------------------------------------- */ - -dl { - margin-bottom: 15px; -} - -dd p { - margin-top: 0px; -} - -dd ul, dd table { - margin-bottom: 10px; -} - -dd { - margin-top: 3px; - margin-bottom: 10px; - margin-left: 30px; -} - -dt:target, .highlight { - background-color: #fbe54e; -} - -dl.glossary dt { - font-weight: bold; - font-size: 1.1em; -} - -.field-list ul { - margin: 0; - padding-left: 1em; -} - -.field-list p { - margin: 0; -} - -.refcount { - color: #060; -} - -.optional { - font-size: 1.3em; -} - -.versionmodified { - font-style: italic; -} - -.system-message { - background-color: #fda; - padding: 5px; - border: 3px solid red; -} - -.footnote:target { - background-color: #ffa -} - -.line-block { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} - -.line-block .line-block { - margin-top: 0; - margin-bottom: 0; - margin-left: 1.5em; -} - -/* -- code displays --------------------------------------------------------- */ - -pre { - overflow: auto; -} - -td.linenos pre { - padding: 5px 0px; - border: 0; - background-color: transparent; - color: #aaa; -} - -table.highlighttable { - margin-left: 0.5em; -} - -table.highlighttable td { - padding: 0 0.5em 0 0.5em; -} - -tt.descname { - background-color: transparent; - font-weight: bold; - font-size: 1.2em; -} - -tt.descclassname { - background-color: transparent; -} - -tt.xref, a tt { - background-color: transparent; - font-weight: bold; -} - -h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { - background-color: transparent; -} - -/* -- math display ---------------------------------------------------------- */ - -img.math { - vertical-align: middle; -} - -div.body div.math p { - text-align: center; -} - -span.eqno { - float: right; -} - -/* -- printout stylesheet --------------------------------------------------- */ - -@media print { - div.document, - div.documentwrapper, - div.bodywrapper { - margin: 0 !important; - width: 100%; - } - - div.sphinxsidebar, - div.related, - div.footer, - #top-link { - display: none; - } -} diff --git a/conductor/doc/source/_static/default.css b/conductor/doc/source/_static/default.css deleted file mode 100644 index c8091ecb..00000000 --- a/conductor/doc/source/_static/default.css +++ /dev/null @@ -1,230 +0,0 @@ -/** - * Sphinx stylesheet -- default theme - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -@import url("basic.css"); - -/* -- page layout ----------------------------------------------------------- */ - -body { - font-family: sans-serif; - font-size: 100%; - background-color: #11303d; - color: #000; - margin: 0; - padding: 0; -} - -div.document { - background-color: #1c4e63; -} - -div.documentwrapper { - float: left; - width: 100%; -} - -div.bodywrapper { - margin: 0 0 0 230px; -} - -div.body { - background-color: #ffffff; - color: #000000; - padding: 0 20px 30px 20px; -} - -div.footer { - color: #ffffff; - width: 100%; - padding: 9px 0 9px 0; - text-align: center; - font-size: 75%; -} - -div.footer a { - color: #ffffff; - text-decoration: underline; -} - -div.related { - background-color: #133f52; - line-height: 30px; - color: #ffffff; -} - -div.related a { - color: #ffffff; -} - -div.sphinxsidebar { -} - -div.sphinxsidebar h3 { - font-family: 'Trebuchet MS', sans-serif; - color: #ffffff; - font-size: 1.4em; - font-weight: normal; - margin: 0; - padding: 0; -} - -div.sphinxsidebar h3 a { - color: #ffffff; -} - -div.sphinxsidebar h4 { - font-family: 'Trebuchet MS', sans-serif; - color: #ffffff; - font-size: 1.3em; - font-weight: normal; - margin: 5px 0 0 0; - padding: 0; -} - -div.sphinxsidebar p { - color: #ffffff; -} - -div.sphinxsidebar p.topless { - margin: 5px 10px 10px 10px; -} - -div.sphinxsidebar ul { - margin: 10px; - padding: 0; - color: #ffffff; -} - -div.sphinxsidebar a { - color: #98dbcc; -} - -div.sphinxsidebar input { - border: 1px solid #98dbcc; - font-family: sans-serif; - font-size: 1em; -} - -/* -- body styles ----------------------------------------------------------- */ - -a { - color: #355f7c; - text-decoration: none; -} - -a:hover { - text-decoration: underline; -} - -div.body p, div.body dd, div.body li { - text-align: left; - line-height: 130%; -} - -div.body h1, -div.body h2, -div.body h3, -div.body h4, -div.body h5, -div.body h6 { - font-family: 'Trebuchet MS', sans-serif; - background-color: #f2f2f2; - font-weight: normal; - color: #20435c; - border-bottom: 1px solid #ccc; - margin: 20px -20px 10px -20px; - padding: 3px 0 3px 10px; -} - -div.body h1 { margin-top: 0; font-size: 200%; } -div.body h2 { font-size: 160%; } -div.body h3 { font-size: 140%; } -div.body h4 { font-size: 120%; } -div.body h5 { font-size: 110%; } -div.body h6 { font-size: 100%; } - -a.headerlink { - color: #c60f0f; - font-size: 0.8em; - padding: 0 4px 0 4px; - text-decoration: none; -} - -a.headerlink:hover { - background-color: #c60f0f; - color: white; -} - -div.body p, div.body dd, div.body li { - text-align: left; - line-height: 130%; -} - -div.admonition p.admonition-title + p { - display: inline; -} - -div.admonition p { - margin-bottom: 5px; -} - -div.admonition pre { - margin-bottom: 5px; -} - -div.admonition ul, div.admonition ol { - margin-bottom: 5px; -} - -div.note { - background-color: #eee; - border: 1px solid #ccc; -} - -div.seealso { - background-color: #ffc; - border: 1px solid #ff6; -} - -div.topic { - background-color: #eee; -} - -div.warning { - background-color: #ffe4e4; - border: 1px solid #f66; -} - -p.admonition-title { - display: inline; -} - -p.admonition-title:after { - content: ":"; -} - -pre { - padding: 5px; - background-color: #eeffcc; - color: #333333; - line-height: 120%; - border: 1px solid #ac9; - border-left: none; - border-right: none; -} - -tt { - background-color: #ecf0f3; - padding: 0 1px 0 1px; - font-size: 0.95em; -} - -.warning tt { - background: #efc2c2; -} - -.note tt { - background: #d6d6d6; -} diff --git a/conductor/doc/source/_static/header-line.gif b/conductor/doc/source/_static/header-line.gif deleted file mode 100644 index 3601730e..00000000 Binary files a/conductor/doc/source/_static/header-line.gif and /dev/null differ diff --git a/conductor/doc/source/_static/header_bg.jpg b/conductor/doc/source/_static/header_bg.jpg deleted file mode 100644 index f788c41c..00000000 Binary files a/conductor/doc/source/_static/header_bg.jpg and /dev/null differ diff --git a/conductor/doc/source/_static/jquery.tweet.js b/conductor/doc/source/_static/jquery.tweet.js deleted file mode 100644 index 79bf0bdb..00000000 --- a/conductor/doc/source/_static/jquery.tweet.js +++ /dev/null @@ -1,154 +0,0 @@ -(function($) { - - $.fn.tweet = function(o){ - var s = { - username: ["seaofclouds"], // [string] required, unless you want to display our tweets. :) it can be an array, just do ["username1","username2","etc"] - list: null, //[string] optional name of list belonging to username - avatar_size: null, // [integer] height and width of avatar if displayed (48px max) - count: 3, // [integer] how many tweets to display? - intro_text: null, // [string] do you want text BEFORE your your tweets? - outro_text: null, // [string] do you want text AFTER your tweets? - join_text: null, // [string] optional text in between date and tweet, try setting to "auto" - auto_join_text_default: "i said,", // [string] auto text for non verb: "i said" bullocks - auto_join_text_ed: "i", // [string] auto text for past tense: "i" surfed - auto_join_text_ing: "i am", // [string] auto tense for present tense: "i was" surfing - auto_join_text_reply: "i replied to", // [string] auto tense for replies: "i replied to" @someone "with" - auto_join_text_url: "i was looking at", // [string] auto tense for urls: "i was looking at" http:... - loading_text: null, // [string] optional loading text, displayed while tweets load - query: null // [string] optional search query - }; - - if(o) $.extend(s, o); - - $.fn.extend({ - linkUrl: function() { - var returning = []; - var regexp = /((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi; - this.each(function() { - returning.push(this.replace(regexp,"<a href=\"$1\">$1</a>")); - }); - return $(returning); - }, - linkUser: function() { - var returning = []; - var regexp = /[\@]+([A-Za-z0-9-_]+)/gi; - this.each(function() { - returning.push(this.replace(regexp,"<a href=\"http://twitter.com/$1\">@$1</a>")); - }); - return $(returning); - }, - linkHash: function() { - var returning = []; - var regexp = / [\#]+([A-Za-z0-9-_]+)/gi; - this.each(function() { - returning.push(this.replace(regexp, ' <a href="http://search.twitter.com/search?q=&tag=$1&lang=all&from='+s.username.join("%2BOR%2B")+'">#$1</a>')); - }); - return $(returning); - }, - capAwesome: function() { - var returning = []; - this.each(function() { - returning.push(this.replace(/\b(awesome)\b/gi, '<span class="awesome">$1</span>')); - }); - return $(returning); - }, - capEpic: function() { - var returning = []; - this.each(function() { - returning.push(this.replace(/\b(epic)\b/gi, '<span class="epic">$1</span>')); - }); - return $(returning); - }, - makeHeart: function() { - var returning = []; - this.each(function() { - returning.push(this.replace(/(&lt;)+[3]/gi, "<tt class='heart'>&#x2665;</tt>")); - }); - return $(returning); - } - }); - - function relative_time(time_value) { - var parsed_date = Date.parse(time_value); - var relative_to = (arguments.length > 1) ? arguments[1] : new Date(); - var delta = parseInt((relative_to.getTime() - parsed_date) / 1000); - var pluralize = function (singular, n) { - return '' + n + ' ' + singular + (n == 1 ? '' : 's'); - }; - if(delta < 60) { - return 'less than a minute ago'; - } else if(delta < (45*60)) { - return 'about ' + pluralize("minute", parseInt(delta / 60)) + ' ago'; - } else if(delta < (24*60*60)) { - return 'about ' + pluralize("hour", parseInt(delta / 3600)) + ' ago'; - } else { - return 'about ' + pluralize("day", parseInt(delta / 86400)) + ' ago'; - } - } - - function build_url() { - var proto = ('https:' == document.location.protocol ? 'https:' : 'http:'); - if (s.list) { - return proto+"//api.twitter.com/1/"+s.username[0]+"/lists/"+s.list+"/statuses.json?per_page="+s.count+"&callback=?"; - } else if (s.query == null && s.username.length == 1) { - return proto+'//twitter.com/status/user_timeline/'+s.username[0]+'.json?count='+s.count+'&callback=?'; - } else { - var query = (s.query || 'from:'+s.username.join('%20OR%20from:')); - return proto+'//search.twitter.com/search.json?&q='+query+'&rpp='+s.count+'&callback=?'; - } - } - - return this.each(function(){ - var list = $('<ul class="tweet_list">').appendTo(this); - var intro = '<p class="tweet_intro">'+s.intro_text+'</p>'; - var outro = '<p class="tweet_outro">'+s.outro_text+'</p>'; - var loading = $('<p class="loading">'+s.loading_text+'</p>'); - - if(typeof(s.username) == "string"){ - s.username = [s.username]; - } - - if (s.loading_text) $(this).append(loading); - $.getJSON(build_url(), function(data){ - if (s.loading_text) loading.remove(); - if (s.intro_text) list.before(intro); - $.each((data.results || data), function(i,item){ - // auto join text based on verb tense and content - if (s.join_text == "auto") { - if (item.text.match(/^(@([A-Za-z0-9-_]+)) .*/i)) { - var join_text = s.auto_join_text_reply; - } else if (item.text.match(/(^\w+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+) .*/i)) { - var join_text = s.auto_join_text_url; - } else if (item.text.match(/^((\w+ed)|just) .*/im)) { - var join_text = s.auto_join_text_ed; - } else if (item.text.match(/^(\w*ing) .*/i)) { - var join_text = s.auto_join_text_ing; - } else { - var join_text = s.auto_join_text_default; - } - } else { - var join_text = s.join_text; - }; - - var from_user = item.from_user || item.user.screen_name; - var profile_image_url = item.profile_image_url || item.user.profile_image_url; - var join_template = '<span class="tweet_join"> '+join_text+' </span>'; - var join = ((s.join_text) ? join_template : ' '); - var avatar_template = '<a class="tweet_avatar" href="http://twitter.com/'+from_user+'"><img src="'+profile_image_url+'" height="'+s.avatar_size+'" width="'+s.avatar_size+'" alt="'+from_user+'\'s avatar" title="'+from_user+'\'s avatar" border="0"/></a>'; - var avatar = (s.avatar_size ? avatar_template : ''); - var date = '<a href="http://twitter.com/'+from_user+'/statuses/'+item.id+'" title="view tweet on twitter">'+relative_time(item.created_at)+'</a>'; - var text = '<span class="tweet_text">' +$([item.text]).linkUrl().linkUser().linkHash().makeHeart().capAwesome().capEpic()[0]+ '</span>'; - - // until we create a template option, arrange the items below to alter a tweet's display. - list.append('<li>' + avatar + date + join + text + '</li>'); - - list.children('li:first').addClass('tweet_first'); - list.children('li:odd').addClass('tweet_even'); - list.children('li:even').addClass('tweet_odd'); - }); - if (s.outro_text) list.after(outro); - }); - - }); - }; -})(jQuery); \ No newline at end of file diff --git a/conductor/doc/source/_static/nature.css b/conductor/doc/source/_static/nature.css deleted file mode 100644 index a98bd420..00000000 --- a/conductor/doc/source/_static/nature.css +++ /dev/null @@ -1,245 +0,0 @@ -/* - * nature.css_t - * ~~~~~~~~~~~~ - * - * Sphinx stylesheet -- nature theme. - * - * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ - -@import url("basic.css"); - -/* -- page layout ----------------------------------------------------------- */ - -body { - font-family: Arial, sans-serif; - font-size: 100%; - background-color: #111; - color: #555; - margin: 0; - padding: 0; -} - -div.documentwrapper { - float: left; - width: 100%; -} - -div.bodywrapper { - margin: 0 0 0 {{ theme_sidebarwidth|toint }}px; -} - -hr { - border: 1px solid #B1B4B6; -} - -div.document { - background-color: #eee; -} - -div.body { - background-color: #ffffff; - color: #3E4349; - padding: 0 30px 30px 30px; - font-size: 0.9em; -} - -div.footer { - color: #555; - width: 100%; - padding: 13px 0; - text-align: center; - font-size: 75%; -} - -div.footer a { - color: #444; - text-decoration: underline; -} - -div.related { - background-color: #6BA81E; - line-height: 32px; - color: #fff; - text-shadow: 0px 1px 0 #444; - font-size: 0.9em; -} - -div.related a { - color: #E2F3CC; -} - -div.sphinxsidebar { - font-size: 0.75em; - line-height: 1.5em; -} - -div.sphinxsidebarwrapper{ - padding: 20px 0; -} - -div.sphinxsidebar h3, -div.sphinxsidebar h4 { - font-family: Arial, sans-serif; - color: #222; - font-size: 1.2em; - font-weight: normal; - margin: 0; - padding: 5px 10px; - background-color: #ddd; - text-shadow: 1px 1px 0 white -} - -div.sphinxsidebar h4{ - font-size: 1.1em; -} - -div.sphinxsidebar h3 a { - color: #444; -} - - -div.sphinxsidebar p { - color: #888; - padding: 5px 20px; -} - -div.sphinxsidebar p.topless { -} - -div.sphinxsidebar ul { - margin: 10px 20px; - padding: 0; - color: #000; -} - -div.sphinxsidebar a { - color: #444; -} - -div.sphinxsidebar input { - border: 1px solid #ccc; - font-family: sans-serif; - font-size: 1em; -} - -div.sphinxsidebar input[type=text]{ - margin-left: 20px; -} - -/* -- body styles ----------------------------------------------------------- */ - -a { - color: #005B81; - text-decoration: none; -} - -a:hover { - color: #E32E00; - text-decoration: underline; -} - -div.body h1, -div.body h2, -div.body h3, -div.body h4, -div.body h5, -div.body h6 { - font-family: Arial, sans-serif; - background-color: #BED4EB; - font-weight: normal; - color: #212224; - margin: 30px 0px 10px 0px; - padding: 5px 0 5px 10px; - text-shadow: 0px 1px 0 white -} - -div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; } -div.body h2 { font-size: 150%; background-color: #C8D5E3; } -div.body h3 { font-size: 120%; background-color: #D8DEE3; } -div.body h4 { font-size: 110%; background-color: #D8DEE3; } -div.body h5 { font-size: 100%; background-color: #D8DEE3; } -div.body h6 { font-size: 100%; background-color: #D8DEE3; } - -a.headerlink { - color: #c60f0f; - font-size: 0.8em; - padding: 0 4px 0 4px; - text-decoration: none; -} - -a.headerlink:hover { - background-color: #c60f0f; - color: white; -} - -div.body p, div.body dd, div.body li { - line-height: 1.5em; -} - -div.admonition p.admonition-title + p { - display: inline; -} - -div.highlight{ - background-color: white; -} - -div.note { - background-color: #eee; - border: 1px solid #ccc; -} - -div.seealso { - background-color: #ffc; - border: 1px solid #ff6; -} - -div.topic { - background-color: #eee; -} - -div.warning { - background-color: #ffe4e4; - border: 1px solid #f66; -} - -p.admonition-title { - display: inline; -} - -p.admonition-title:after { - content: ":"; -} - -pre { - padding: 10px; - background-color: White; - color: #222; - line-height: 1.2em; - border: 1px solid #C6C9CB; - font-size: 1.1em; - margin: 1.5em 0 1.5em 0; - -webkit-box-shadow: 1px 1px 1px #d8d8d8; - -moz-box-shadow: 1px 1px 1px #d8d8d8; -} - -tt { - background-color: #ecf0f3; - color: #222; - /* padding: 1px 2px; */ - font-size: 1.1em; - font-family: monospace; -} - -.viewcode-back { - font-family: Arial, sans-serif; -} - -div.viewcode-block:target { - background-color: #f4debf; - border-top: 1px solid #ac9; - border-bottom: 1px solid #ac9; -} diff --git a/conductor/doc/source/_static/openstack_logo.png b/conductor/doc/source/_static/openstack_logo.png deleted file mode 100644 index 146faec5..00000000 Binary files a/conductor/doc/source/_static/openstack_logo.png and /dev/null differ diff --git a/conductor/doc/source/_static/tweaks.css b/conductor/doc/source/_static/tweaks.css deleted file mode 100644 index 3f3fb3f0..00000000 --- a/conductor/doc/source/_static/tweaks.css +++ /dev/null @@ -1,94 +0,0 @@ -body { - background: #fff url(../_static/header_bg.jpg) top left no-repeat; -} - -#header { - width: 950px; - margin: 0 auto; - height: 102px; -} - -#header h1#logo { - background: url(../_static/openstack_logo.png) top left no-repeat; - display: block; - float: left; - text-indent: -9999px; - width: 175px; - height: 55px; -} - -#navigation { - background: url(../_static/header-line.gif) repeat-x 0 bottom; - display: block; - float: left; - margin: 27px 0 0 25px; - padding: 0; -} - -#navigation li{ - float: left; - display: block; - margin-right: 25px; -} - -#navigation li a { - display: block; - font-weight: normal; - text-decoration: none; - background-position: 50% 0; - padding: 20px 0 5px; - color: #353535; - font-size: 14px; -} - -#navigation li a.current, #navigation li a.section { - border-bottom: 3px solid #cf2f19; - color: #cf2f19; -} - -div.related { - background-color: #cde2f8; - border: 1px solid #b0d3f8; -} - -div.related a { - color: #4078ba; - text-shadow: none; -} - -div.sphinxsidebarwrapper { - padding-top: 0; -} - -pre { - color: #555; -} - -div.documentwrapper h1, div.documentwrapper h2, div.documentwrapper h3, div.documentwrapper h4, div.documentwrapper h5, div.documentwrapper h6 { - font-family: 'PT Sans', sans-serif !important; - color: #264D69; - border-bottom: 1px dotted #C5E2EA; - padding: 0; - background: none; - padding-bottom: 5px; -} - -div.documentwrapper h3 { - color: #CF2F19; -} - -a.headerlink { - color: #fff !important; - margin-left: 5px; - background: #CF2F19 !important; -} - -div.body { - margin-top: -25px; - margin-left: 230px; -} - -div.document { - width: 960px; - margin: 0 auto; -} \ No newline at end of file diff --git a/conductor/doc/source/_templates/.placeholder b/conductor/doc/source/_templates/.placeholder deleted file mode 100644 index e69de29b..00000000 diff --git a/conductor/doc/source/_theme/layout.html b/conductor/doc/source/_theme/layout.html deleted file mode 100644 index 750b7822..00000000 --- a/conductor/doc/source/_theme/layout.html +++ /dev/null @@ -1,83 +0,0 @@ -{% extends "basic/layout.html" %} -{% set css_files = css_files + ['_static/tweaks.css'] %} -{% set script_files = script_files + ['_static/jquery.tweet.js'] %} - -{%- macro sidebar() %} - {%- if not embedded %}{% if not theme_nosidebar|tobool %} - <div class="sphinxsidebar"> - <div class="sphinxsidebarwrapper"> - {%- block sidebarlogo %} - {%- if logo %} - <p class="logo"><a href="{{ pathto(master_doc) }}"> - <img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/> - </a></p> - {%- endif %} - {%- endblock %} - {%- block sidebartoc %} - {%- if display_toc %} - <h3><a href="{{ pathto(master_doc) }}">{{ _('Table Of Contents') }}</a></h3> - {{ toc }} - {%- endif %} - {%- endblock %} - {%- block sidebarrel %} - {%- if prev %} - <h4>{{ _('Previous topic') }}</h4> - <p class="topless"><a href="{{ prev.link|e }}" - title="{{ _('previous chapter') }}">{{ prev.title }}</a></p> - {%- endif %} - {%- if next %} - <h4>{{ _('Next topic') }}</h4> - <p class="topless"><a href="{{ next.link|e }}" - title="{{ _('next chapter') }}">{{ next.title }}</a></p> - {%- endif %} - {%- endblock %} - {%- block sidebarsourcelink %} - {%- if show_source and has_source and sourcename %} - <h3>{{ _('This Page') }}</h3> - <ul class="this-page-menu"> - <li><a href="{{ pathto('_sources/' + sourcename, true)|e }}" - rel="nofollow">{{ _('Show Source') }}</a></li> - </ul> - {%- endif %} - {%- endblock %} - {%- if customsidebar %} - {% include customsidebar %} - {%- endif %} - {%- block sidebarsearch %} - {%- if pagename != "search" %} - <div id="searchbox" style="display: none"> - <h3>{{ _('Quick search') }}</h3> - <form class="search" action="{{ pathto('search') }}" method="get"> - <input type="text" name="q" size="18" /> - <input type="submit" value="{{ _('Go') }}" /> - <input type="hidden" name="check_keywords" value="yes" /> - <input type="hidden" name="area" value="default" /> - </form> - <p class="searchtip" style="font-size: 90%"> - {{ _('Enter search terms or a module, class or function name.') }} - </p> - </div> - <script type="text/javascript">$('#searchbox').show(0);</script> - {%- endif %} - {%- endblock %} - </div> - </div> - {%- endif %}{% endif %} -{%- endmacro %} - -{% block relbar1 %}{% endblock relbar1 %} - -{% block header %} - <div id="header"> - <h1 id="logo"><a href="http://www.openstack.org/">OpenStack</a></h1> - <ul id="navigation"> - <li><a href="http://www.openstack.org/" title="Go to the Home page" class="link">Home</a></li> - <li><a href="http://www.openstack.org/projects/" title="Go to the OpenStack Projects page">Projects</a></li> - <li><a href="http://www.openstack.org/user-stories/" title="Go to the User Stories page" class="link">User Stories</a></li> - <li><a href="http://www.openstack.org/community/" title="Go to the Community page" class="link">Community</a></li> - <li><a href="http://www.openstack.org/blog/" title="Go to the OpenStack Blog">Blog</a></li> - <li><a href="http://wiki.openstack.org/" title="Go to the OpenStack Wiki">Wiki</a></li> - <li><a href="http://docs.openstack.org/" title="Go to OpenStack Documentation" class="current">Documentation</a></li> - </ul> - </div> -{% endblock %} \ No newline at end of file diff --git a/conductor/doc/source/_theme/theme.conf b/conductor/doc/source/_theme/theme.conf deleted file mode 100644 index 1cc40044..00000000 --- a/conductor/doc/source/_theme/theme.conf +++ /dev/null @@ -1,4 +0,0 @@ -[theme] -inherit = basic -stylesheet = nature.css -pygments_style = tango diff --git a/conductor/doc/source/conf.py b/conductor/doc/source/conf.py deleted file mode 100644 index e9b38f91..00000000 --- a/conductor/doc/source/conf.py +++ /dev/null @@ -1,242 +0,0 @@ - -# -*- coding: utf-8 -*- -# Copyright (c) 2010 OpenStack Foundation. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# -# Conductor documentation build configuration file, created by -# sphinx-quickstart on Tue February 28 13:50:15 2013. -# -# This file is execfile()'d with the current directory set to its containing -# dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import os -import sys - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path = [os.path.abspath('../../conductor'), - os.path.abspath('../..'), - os.path.abspath('../../bin') - ] + sys.path - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.coverage', - 'sphinx.ext.ifconfig', - 'sphinx.ext.intersphinx', - 'sphinx.ext.pngmath', - 'sphinx.ext.graphviz'] - -# Add any paths that contain templates here, relative to this directory. -templates_path = [] -if os.getenv('HUDSON_PUBLISH_DOCS'): - templates_path = ['_ga', '_templates'] -else: - templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'Conductor' -copyright = u'2013, Mirantis, Inc.' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -from conductor.version import version_info as conductor_version -# The full version, including alpha/beta/rc tags. -release = conductor_version.version_string_with_vcs() -# The short X.Y version. -version = conductor_version.canonical_version_string() - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of documents that shouldn't be included in the build. -#unused_docs = [] - -# List of directories, relative to source directory, that shouldn't be searched -# for source files. -exclude_trees = ['api'] - -# The reST default role (for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -show_authors = True - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -modindex_common_prefix = ['portas.'] - -# -- Options for man page output -------------------------------------------- - -# Grouping the document tree for man pages. -# List of tuples 'sourcefile', 'target', u'title', u'Authors name', 'manual' - -man_pages = [ - ('man/conductor', 'conductor', u'Conductor Orchestrator', - [u'Mirantis, Inc.'], 1) -] - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -html_theme_path = ["."] -html_theme = '_theme' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = ['_theme'] - -# The name for this set of Sphinx documents. If None, it defaults to -# "<project> v<release> documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' -git_cmd = "git log --pretty=format:'%ad, commit %h' --date=local -n1" -html_last_updated_fmt = os.popen(git_cmd).read() - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -html_use_modindex = False - -# If false, no index is generated. -html_use_index = False - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a <link> tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = '' - -# Output file base name for HTML help builder. -htmlhelp_basename = 'conductordoc' - - -# -- Options for LaTeX output ------------------------------------------------ - -# The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' - -# The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, -# documentclass [howto/manual]). -latex_documents = [ - ('index', 'Conductor.tex', u'Conductor Documentation', - u'Keero Team', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# Additional stuff for the LaTeX preamble. -#latex_preamble = '' - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_use_modindex = True - -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'python': ('http://docs.python.org/', None)} diff --git a/conductor/doc/source/index.rst b/conductor/doc/source/index.rst deleted file mode 100644 index ea1b15b3..00000000 --- a/conductor/doc/source/index.rst +++ /dev/null @@ -1,72 +0,0 @@ -.. - Copyright 2010 OpenStack Foundation - All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); you may - not use this file except in compliance with the License. You may obtain - a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - License for the specific language governing permissions and limitations - under the License. - -======================================================= -Welcome to Conductor, the Glazier orchestration engine! -======================================================= - -Conductor is an Glazier orchestration engine that transforms object model sent by -REST API service into a series of Heat and Glazier-Agent commands - -This document describes Conductor for contributors of the project. - -This documentation is generated by the Sphinx toolkit and lives in the source -tree. - -Installation Guide -================== -Install -------- - - Check out sources to some directory (<home>/glazier): - - smelikyan@work:~/git clone ssh://<user>@gerrit.mirantis.com:29418/keero/keero.git - - Install Conductor: - - smelikyan@work:~/cd glazier/conductor && sudo python setup.py install - -Configure ---------- - - Open configuration file for editing: - - smelikyan@work:~/cd glazier/conductor/etc && nano conductor.conf - - Configure according to you environment: - [DEFAULT] - log_file = logs/conductor.log - debug=True - verbose=True - - [heat] - auth_url = http://localhost:5000/v2.0 - - [rabbitmq] - # this must be IP or hostname accessible from instances (VMs) - host = YOUR.REAL.IP.HERE - port = 5672 - virtual_host = glazier - login = glazier - password = glazier - -Run ----- - -Run Conductor and supply valid configuration file: - -smelikyan@work:~/cd glazier/conductor && conductor --config-file=./glazier/conductor/etc/conductor.conf - diff --git a/conductor/etc/conductor-paste.ini b/conductor/etc/conductor-paste.ini deleted file mode 100644 index e69de29b..00000000 diff --git a/conductor/etc/conductor.conf b/conductor/etc/conductor.conf deleted file mode 100644 index 60f3202f..00000000 --- a/conductor/etc/conductor.conf +++ /dev/null @@ -1,14 +0,0 @@ -[DEFAULT] -log_file = logs/conductor.log -debug=True -verbose=True - -[heat] -auth_url = http://172.18.124.101:5000/v2.0 - -[rabbitmq] -host = 172.18.124.101 -port = 5672 -virtual_host = keero -login = keero -password = keero \ No newline at end of file diff --git a/conductor/logs/.gitignore b/conductor/logs/.gitignore deleted file mode 100644 index 44c5ea8f..00000000 --- a/conductor/logs/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore \ No newline at end of file diff --git a/conductor/openstack-common.conf b/conductor/openstack-common.conf deleted file mode 100644 index 04377376..00000000 --- a/conductor/openstack-common.conf +++ /dev/null @@ -1,7 +0,0 @@ -[DEFAULT] - -# The list of modules to copy from openstack-common -modules=setup,wsgi,config,exception,gettextutils,importutils,jsonutils,log,xmlutils,sslutils,service,notifier,local,install_venv_common,version,timeutils,eventlet_backdoor,threadgroup,loopingcall,uuidutils - -# The base module to hold the copy of openstack.common -base=conductor \ No newline at end of file diff --git a/conductor/run_tests.sh b/conductor/run_tests.sh deleted file mode 100755 index ba2c9e01..00000000 --- a/conductor/run_tests.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash - -function usage { - echo "Usage: $0 [OPTION]..." - echo "Run python-portasclient's test suite(s)" - echo "" - echo " -p, --pep8 Just run pep8" - echo " -h, --help Print this usage message" - echo "" - echo "This script is deprecated and currently retained for compatibility." - echo 'You can run the full test suite for multiple environments by running "tox".' - echo 'You can run tests for only python 2.7 by running "tox -e py27", or run only' - echo 'the pep8 tests with "tox -e pep8".' - exit -} - -command -v tox > /dev/null 2>&1 -if [ $? -ne 0 ]; then - echo 'This script requires "tox" to run.' - echo 'You can install it with "pip install tox".' - exit 1; -fi - -just_pep8=0 - -function process_option { - case "$1" in - -h|--help) usage;; - -p|--pep8) let just_pep8=1;; - esac -} - -for arg in "$@"; do - process_option $arg -done - -if [ $just_pep8 -eq 1 ]; then - tox -e pep8 - exit -fi - -tox -e py27 $toxargs 2>&1 | tee run_tests.err.log || exit -if [ ${PIPESTATUS[0]} -ne 0 ]; then - exit ${PIPESTATUS[0]} -fi - -if [ -z "$toxargs" ]; then - tox -e pep8 -fi diff --git a/conductor/setup.cfg b/conductor/setup.cfg deleted file mode 100644 index 6e6f6554..00000000 --- a/conductor/setup.cfg +++ /dev/null @@ -1,33 +0,0 @@ -[build_sphinx] -all_files = 1 -build-dir = doc/build -source-dir = doc/source - -[egg_info] -tag_build = -tag_date = 0 -tag_svn_revision = 0 - -[compile_catalog] -directory = conductor/locale -domain = conductor - -[update_catalog] -domain = conductor -output_dir = conductor/locale -input_file = conductor/locale/conductor.pot - -[extract_messages] -keywords = _ gettext ngettext l_ lazy_gettext -mapping_file = babel.cfg -output_file = conductor/locale/conductor.pot - -[nosetests] -# NOTE(jkoelker) To run the test suite under nose install the following -# coverage http://pypi.python.org/pypi/coverage -# tissue http://pypi.python.org/pypi/tissue (pep8 checker) -# openstack-nose https://github.com/jkoelker/openstack-nose -verbosity=2 -cover-package = conductor -cover-html = true -cover-erase = true \ No newline at end of file diff --git a/conductor/setup.py b/conductor/setup.py deleted file mode 100644 index fb9da8cd..00000000 --- a/conductor/setup.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/python -# Copyright (c) 2010 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import setuptools - -from conductor.openstack.common import setup - -requires = setup.parse_requirements() -depend_links = setup.parse_dependency_links() -project = 'conductor' - -setuptools.setup( - name=project, - version=setup.get_version(project, '2013.1'), - description='The Conductor is orchestration engine server', - license='Apache License (2.0)', - author='Mirantis, Inc.', - author_email='openstack@lists.launchpad.net', - url='http://conductor.openstack.org/', - packages=setuptools.find_packages(exclude=['bin']), - test_suite='nose.collector', - cmdclass=setup.get_cmdclass(), - include_package_data=True, - install_requires=requires, - dependency_links=depend_links, - classifiers=[ - 'Development Status :: 4 - Beta', - 'License :: OSI Approved :: Apache Software License', - 'Operating System :: POSIX :: Linux', - 'Programming Language :: Python :: 2.7', - 'Environment :: No Input/Output (Daemon)', - 'Environment :: OpenStack', - ], - scripts=['bin/conductor'], - py_modules=[] -) diff --git a/conductor/test.json b/conductor/test.json deleted file mode 100644 index c2815d50..00000000 --- a/conductor/test.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "MyDataCenterx", - "id": "adc6d143f9584d10808c7ef4d07e4802", - "token": "MIINIQYJKoZIhvcNAQcCoIINEjCCDQ4CAQExCTAHBgUrDgMCGjCCC-oGCSqGSIb3DQEHAaCCC+sEggvneyJhY2Nlc3MiOiB7InRva2VuIjogeyJpc3N1ZWRfYXQiOiAiMjAxMy0wMy0yNlQwNjo0NTozNy4zOTI0MDAiLCAiZXhwaXJlcyI6ICIyMDEzLTAzLTI3VDA2OjQ1OjM3WiIsICJpZCI6ICJwbGFjZWhvbGRlciIsICJ0ZW5hbnQiOiB7ImRlc2NyaXB0aW9uIjogbnVsbCwgImVuYWJsZWQiOiB0cnVlLCAiaWQiOiAiMTZlYjc4Y2JiNjg4NDU5YzgzMDhkODk2NzhiY2VmNTAiLCAibmFtZSI6ICJhZG1pbiJ9fSwgInNlcnZpY2VDYXRhbG9nIjogW3siZW5kcG9pbnRzIjogW3siYWRtaW5VUkwiOiAiaHR0cDovLzE3Mi4xOC4xMjQuMTAxOjg3NzQvdjIvMTZlYjc4Y2JiNjg4NDU5YzgzMDhkODk2NzhiY2VmNTAiLCAicmVnaW9uIjogIlJlZ2lvbk9uZSIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTcyLjE4LjEyNC4xMDE6ODc3NC92Mi8xNmViNzhjYmI2ODg0NTljODMwOGQ4OTY3OGJjZWY1MCIsICJpZCI6ICIwNGFlNjM2ZTdhYzc0NmJjYjExM2EwYzI5NDYzMzgzMCIsICJwdWJsaWNVUkwiOiAiaHR0cDovLzE3Mi4xOC4xMjQuMTAxOjg3NzQvdjIvMTZlYjc4Y2JiNjg4NDU5YzgzMDhkODk2NzhiY2VmNTAifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiY29tcHV0ZSIsICJuYW1lIjogIm5vdmEifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE4LjEyNC4xMDE6MzMzMyIsICJyZWdpb24iOiAiUmVnaW9uT25lIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTguMTI0LjEwMTozMzMzIiwgImlkIjogIjA5MmJkMjMyMGU5ZDRlYWY4ZDBlZjEzNDhjOGU3NTJjIiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTcyLjE4LjEyNC4xMDE6MzMzMyJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJzMyIsICJuYW1lIjogInMzIn0sIHsiZW5kcG9pbnRzIjogW3siYWRtaW5VUkwiOiAiaHR0cDovLzE3Mi4xOC4xMjQuMTAxOjkyOTIiLCAicmVnaW9uIjogIlJlZ2lvbk9uZSIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTcyLjE4LjEyNC4xMDE6OTI5MiIsICJpZCI6ICI1ZWUzNjdjYzRhNjY0YmQzYTYyNmI2MjBkMzFhYzcwYyIsICJwdWJsaWNVUkwiOiAiaHR0cDovLzE3Mi4xOC4xMjQuMTAxOjkyOTIifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiaW1hZ2UiLCAibmFtZSI6ICJnbGFuY2UifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE4LjEyNC4xMDE6ODAwMC92MSIsICJyZWdpb24iOiAiUmVnaW9uT25lIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTguMTI0LjEwMTo4MDAwL3YxIiwgImlkIjogIjM3MzMzYmQwNDkxOTQzY2FiNWEyZGM5N2I5YWQzYjE2IiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTcyLjE4LjEyNC4xMDE6ODAwMC92MSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJjbG91ZGZvcm1hdGlvbiIsICJuYW1lIjogImhlYXQtY2ZuIn0sIHsiZW5kcG9pbnRzIjogW3siYWRtaW5VUkwiOiAiaHR0cDovLzE3Mi4xOC4xMjQuMTAxOjg3NzYvdjEvMTZlYjc4Y2JiNjg4NDU5YzgzMDhkODk2NzhiY2VmNTAiLCAicmVnaW9uIjogIlJlZ2lvbk9uZSIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTcyLjE4LjEyNC4xMDE6ODc3Ni92MS8xNmViNzhjYmI2ODg0NTljODMwOGQ4OTY3OGJjZWY1MCIsICJpZCI6ICI4NTgwYjMzOTAxZWU0YTUyOWI0OGMyMzU0ZjFiMWNhZSIsICJwdWJsaWNVUkwiOiAiaHR0cDovLzE3Mi4xOC4xMjQuMTAxOjg3NzYvdjEvMTZlYjc4Y2JiNjg4NDU5YzgzMDhkODk2NzhiY2VmNTAifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAidm9sdW1lIiwgIm5hbWUiOiAiY2luZGVyIn0sIHsiZW5kcG9pbnRzIjogW3siYWRtaW5VUkwiOiAiaHR0cDovLzE3Mi4xOC4xMjQuMTAxOjg3NzMvc2VydmljZXMvQWRtaW4iLCAicmVnaW9uIjogIlJlZ2lvbk9uZSIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTcyLjE4LjEyNC4xMDE6ODc3My9zZXJ2aWNlcy9DbG91ZCIsICJpZCI6ICIwYTViOTIyNTNiZjg0NTAwYTA4OWY1N2VkMmYzZDY3NSIsICJwdWJsaWNVUkwiOiAiaHR0cDovLzE3Mi4xOC4xMjQuMTAxOjg3NzMvc2VydmljZXMvQ2xvdWQifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiZWMyIiwgIm5hbWUiOiAiZWMyIn0sIHsiZW5kcG9pbnRzIjogW3siYWRtaW5VUkwiOiAiaHR0cDovLzE3Mi4xOC4xMjQuMTAxOjgwMDQvdjEvMTZlYjc4Y2JiNjg4NDU5YzgzMDhkODk2NzhiY2VmNTAiLCAicmVnaW9uIjogIlJlZ2lvbk9uZSIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTcyLjE4LjEyNC4xMDE6ODAwNC92MS8xNmViNzhjYmI2ODg0NTljODMwOGQ4OTY3OGJjZWY1MCIsICJpZCI6ICJhMjRjMGY1ZmUzMmQ0ZDU5YWEwMTk1Mzg3OGFlMDQwNyIsICJwdWJsaWNVUkwiOiAiaHR0cDovLzE3Mi4xOC4xMjQuMTAxOjgwMDQvdjEvMTZlYjc4Y2JiNjg4NDU5YzgzMDhkODk2NzhiY2VmNTAifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAib3JjaGVzdHJhdGlvbiIsICJuYW1lIjogImhlYXQifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE4LjEyNC4xMDE6MzUzNTcvdjIuMCIsICJyZWdpb24iOiAiUmVnaW9uT25lIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTguMTI0LjEwMTo1MDAwL3YyLjAiLCAiaWQiOiAiNGM4M2VlYjk3MDA5NDg3M2FiNjg3NjUzNWJlZjgxZWEiLCAicHVibGljVVJMIjogImh0dHA6Ly8xNzIuMTguMTI0LjEwMTo1MDAwL3YyLjAifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiaWRlbnRpdHkiLCAibmFtZSI6ICJrZXlzdG9uZSJ9XSwgInVzZXIiOiB7InVzZXJuYW1lIjogImFkbWluIiwgInJvbGVzX2xpbmtzIjogW10sICJpZCI6ICJmMmNkZWM4NTQ2MmQ0N2UzODQ5ZTZmMzE3NGRhMTk4NSIsICJyb2xlcyI6IFt7Im5hbWUiOiAiYWRtaW4ifV0sICJuYW1lIjogImFkbWluIn0sICJtZXRhZGF0YSI6IHsiaXNfYWRtaW4iOiAwLCAicm9sZXMiOiBbIjc4N2JlODdjMGFkMjQ3ODJiNTQ4NWU5NjNhZjllNzllIl19fX0xgf8wgfwCAQEwXDBXMQswCQYDVQQGEwJVUzEOMAwGA1UECBMFVW5zZXQxDjAMBgNVBAcTBVVuc2V0MQ4wDAYDVQQKEwVVbnNldDEYMBYGA1UEAxMPd3d3LmV4YW1wbGUuY29tAgEBMAcGBSsOAwIaMA0GCSqGSIb3DQEBAQUABIGAURfgqd8iZ-UWZTta2pyKzXBXm9nmdzlOY-TN8526LWH4jrU1uuimAZKSjZUCwmnaSvoXHLlP6CSGvNUJWDDu6YFNmDfmatVqFrTij4EFGruExmtUxmhbQOnAyhKqIxHFg2t3VKEB2tVhLGSzoSH1dM2+j0-I0JgOLWIStVFEF5A=", - "services": { - "activeDirectories": [ - { - "id": "9571747991184642B95F430A014616F9", - "domain": "acme.loc", - "adminPassword": "SuperP@ssw0rd!", - "units": [ - { - "id": "273c9183b6e74c9c9db7fdd532c5eb25", - "name": "dc01", - "isMaster": true, - "recoveryPassword": "2SuperP@ssw0rd2" - }, - { - "id": "377c6f16d17a416791f80724dab360c6", - "name": "dc02", - "isMaster": false, - "adminPassword": "SuperP@ssw0rd", - "recoveryPassword": "2SuperP@ssw0rd2" - } - ] - } - ], - "webServers": [ - { - "id": "e9657ceef84a4e669e31795040080262", - "domain": "acme.loc", - "units": [ - { - "id": "e6f9cfd07ced48fba64e6bd9e65aba64", - "name": "iis01", - "adminPassword": "SuperP@ssw0rd" - } - ] - } - ] - } -} diff --git a/conductor/tests/__init__.py b/conductor/tests/__init__.py deleted file mode 100644 index e3f3e8d4..00000000 --- a/conductor/tests/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. diff --git a/conductor/tests/conductor/__init__.py b/conductor/tests/conductor/__init__.py deleted file mode 100644 index e3f3e8d4..00000000 --- a/conductor/tests/conductor/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. diff --git a/conductor/tests/conductor/test_methods.py b/conductor/tests/conductor/test_methods.py deleted file mode 100644 index 68c4edeb..00000000 --- a/conductor/tests/conductor/test_methods.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import unittest -from conductor.app import ConductorWorkflowService -import conductor.rabbitmq as rabbitmq -from conductor.workflow import Workflow -import conductor.xml_code_engine as engine - -class TestMethodsAndClasses(unittest.TestCase): - - def test_init_service_class(self): - con = ConductorWorkflowService() - - con.start() - con.stop() diff --git a/conductor/tests/conductor/test_with_fake_service.py b/conductor/tests/conductor/test_with_fake_service.py deleted file mode 100644 index ca380b1c..00000000 --- a/conductor/tests/conductor/test_with_fake_service.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import unittest -from conductor.app import ConductorWorkflowService -from conductor.openstack.common import service - -class TestMethodsAndClasses(unittest.TestCase): - - def test_init_service_class(self): - launcher = service.ServiceLauncher() - con = ConductorWorkflowService() - launcher.launch_service(con) - diff --git a/conductor/tests/soapui.log b/conductor/tests/soapui.log deleted file mode 100644 index e69de29b..00000000 diff --git a/conductor/tools/install_venv.py b/conductor/tools/install_venv.py deleted file mode 100644 index c3b81718..00000000 --- a/conductor/tools/install_venv.py +++ /dev/null @@ -1,154 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Copyright 2010 OpenStack LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Installation script for Glance's development virtualenv -""" - -import os -import subprocess -import sys - - -ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) -VENV = os.path.join(ROOT, '.venv') -PIP_REQUIRES = os.path.join(ROOT, 'tools', 'pip-requires') -TEST_REQUIRES = os.path.join(ROOT, 'tools', 'test-requires') - - -def die(message, *args): - print >> sys.stderr, message % args - sys.exit(1) - - -def run_command(cmd, redirect_output=True, check_exit_code=True): - """ - Runs a command in an out-of-process shell, returning the - output of that command. Working directory is ROOT. - """ - if redirect_output: - stdout = subprocess.PIPE - else: - stdout = None - - proc = subprocess.Popen(cmd, cwd=ROOT, stdout=stdout) - output = proc.communicate()[0] - if check_exit_code and proc.returncode != 0: - die('Command "%s" failed.\n%s', ' '.join(cmd), output) - return output - - -HAS_EASY_INSTALL = bool(run_command(['which', 'easy_install'], - check_exit_code=False).strip()) -HAS_VIRTUALENV = bool(run_command(['which', 'virtualenv'], - check_exit_code=False).strip()) - - -def check_dependencies(): - """Make sure virtualenv is in the path.""" - - if not HAS_VIRTUALENV: - print 'not found.' - # Try installing it via easy_install... - if HAS_EASY_INSTALL: - print 'Installing virtualenv via easy_install...', - if not run_command(['which', 'easy_install']): - die('ERROR: virtualenv not found.\n\n' - 'Balancer development requires virtualenv, please install' - ' it using your favorite package management tool') - print 'done.' - print 'done.' - - -def create_virtualenv(venv=VENV): - """ - Creates the virtual environment and installs PIP only into the - virtual environment - """ - print 'Creating venv...', - run_command(['virtualenv', '-q', '--no-site-packages', VENV]) - print 'done.' - print 'Installing pip in virtualenv...', - if not run_command(['tools/with_venv.sh', 'easy_install', - 'pip>1.0']).strip(): - die("Failed to install pip.") - print 'done.' - - -def pip_install(*args): - run_command(['tools/with_venv.sh', - 'pip', 'install', '--upgrade'] + list(args), - redirect_output=False) - - -def install_dependencies(venv=VENV): - print 'Installing dependencies with pip (this can take a while)...' - - pip_install('pip') - - pip_install('-r', PIP_REQUIRES) - pip_install('-r', TEST_REQUIRES) - - # Tell the virtual env how to "import glance" - py_ver = _detect_python_version(venv) - pthfile = os.path.join(venv, "lib", py_ver, - "site-packages", "balancer.pth") - f = open(pthfile, 'w') - f.write("%s\n" % ROOT) - - -def _detect_python_version(venv): - lib_dir = os.path.join(venv, "lib") - for pathname in os.listdir(lib_dir): - if pathname.startswith('python'): - return pathname - raise Exception('Unable to detect Python version') - - -def print_help(): - help = """ - Glance development environment setup is complete. - - Glance development uses virtualenv to track and manage Python dependencies - while in development and testing. - - To activate the Glance virtualenv for the extent of your current shell session - you can run: - - $ source .venv/bin/activate - - Or, if you prefer, you can run commands in the virtualenv on a case by case - basis by running: - - $ tools/with_venv.sh <your command> - - Also, make test will automatically use the virtualenv. - """ - print help - - -def main(argv): - check_dependencies() - create_virtualenv() - install_dependencies() - print_help() - -if __name__ == '__main__': - main(sys.argv) diff --git a/conductor/tools/install_venv_common.py b/conductor/tools/install_venv_common.py deleted file mode 100644 index 41306564..00000000 --- a/conductor/tools/install_venv_common.py +++ /dev/null @@ -1,220 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2013 OpenStack Foundation -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides methods needed by installation script for OpenStack development -virtual environments. - -Synced in from openstack-common -""" - -import argparse -import os -import subprocess -import sys - - -class InstallVenv(object): - - def __init__(self, root, venv, pip_requires, test_requires, py_version, - project): - self.root = root - self.venv = venv - self.pip_requires = pip_requires - self.test_requires = test_requires - self.py_version = py_version - self.project = project - - def die(self, message, *args): - print >> sys.stderr, message % args - sys.exit(1) - - def check_python_version(self): - if sys.version_info < (2, 6): - self.die("Need Python Version >= 2.6") - - def run_command_with_code(self, cmd, redirect_output=True, - check_exit_code=True): - """Runs a command in an out-of-process shell. - - Returns the output of that command. Working directory is self.root. - """ - if redirect_output: - stdout = subprocess.PIPE - else: - stdout = None - - proc = subprocess.Popen(cmd, cwd=self.root, stdout=stdout) - output = proc.communicate()[0] - if check_exit_code and proc.returncode != 0: - self.die('Command "%s" failed.\n%s', ' '.join(cmd), output) - return (output, proc.returncode) - - def run_command(self, cmd, redirect_output=True, check_exit_code=True): - return self.run_command_with_code(cmd, redirect_output, - check_exit_code)[0] - - def get_distro(self): - if (os.path.exists('/etc/fedora-release') or - os.path.exists('/etc/redhat-release')): - return Fedora(self.root, self.venv, self.pip_requires, - self.test_requires, self.py_version, self.project) - else: - return Distro(self.root, self.venv, self.pip_requires, - self.test_requires, self.py_version, self.project) - - def check_dependencies(self): - self.get_distro().install_virtualenv() - - def create_virtualenv(self, no_site_packages=True): - """Creates the virtual environment and installs PIP. - - Creates the virtual environment and installs PIP only into the - virtual environment. - """ - if not os.path.isdir(self.venv): - print 'Creating venv...', - if no_site_packages: - self.run_command(['virtualenv', '-q', '--no-site-packages', - self.venv]) - else: - self.run_command(['virtualenv', '-q', self.venv]) - print 'done.' - print 'Installing pip in venv...', - if not self.run_command(['tools/with_venv.sh', 'easy_install', - 'pip>1.0']).strip(): - self.die("Failed to install pip.") - print 'done.' - else: - print "venv already exists..." - pass - - def pip_install(self, *args): - self.run_command(['tools/with_venv.sh', - 'pip', 'install', '--upgrade'] + list(args), - redirect_output=False) - - def install_dependencies(self): - print 'Installing dependencies with pip (this can take a while)...' - - # First things first, make sure our venv has the latest pip and - # distribute. - # NOTE: we keep pip at version 1.1 since the most recent version causes - # the .venv creation to fail. See: - # https://bugs.launchpad.net/nova/+bug/1047120 - self.pip_install('pip==1.1') - self.pip_install('distribute') - - # Install greenlet by hand - just listing it in the requires file does - # not - # get it installed in the right order - self.pip_install('greenlet') - - self.pip_install('-r', self.pip_requires) - self.pip_install('-r', self.test_requires) - - def post_process(self): - self.get_distro().post_process() - - def parse_args(self, argv): - """Parses command-line arguments.""" - parser = argparse.ArgumentParser() - parser.add_argument('-n', '--no-site-packages', - action='store_true', - help="Do not inherit packages from global Python " - "install") - return parser.parse_args(argv[1:]) - - -class Distro(InstallVenv): - - def check_cmd(self, cmd): - return bool(self.run_command(['which', cmd], - check_exit_code=False).strip()) - - def install_virtualenv(self): - if self.check_cmd('virtualenv'): - return - - if self.check_cmd('easy_install'): - print 'Installing virtualenv via easy_install...', - if self.run_command(['easy_install', 'virtualenv']): - print 'Succeeded' - return - else: - print 'Failed' - - self.die('ERROR: virtualenv not found.\n\n%s development' - ' requires virtualenv, please install it using your' - ' favorite package management tool' % self.project) - - def post_process(self): - """Any distribution-specific post-processing gets done here. - - In particular, this is useful for applying patches to code inside - the venv. - """ - pass - - -class Fedora(Distro): - """This covers all Fedora-based distributions. - - Includes: Fedora, RHEL, CentOS, Scientific Linux - """ - - def check_pkg(self, pkg): - return self.run_command_with_code(['rpm', '-q', pkg], - check_exit_code=False)[1] == 0 - - def yum_install(self, pkg, **kwargs): - print "Attempting to install '%s' via yum" % pkg - self.run_command(['sudo', 'yum', 'install', '-y', pkg], **kwargs) - - def apply_patch(self, originalfile, patchfile): - self.run_command(['patch', '-N', originalfile, patchfile], - check_exit_code=False) - - def install_virtualenv(self): - if self.check_cmd('virtualenv'): - return - - if not self.check_pkg('python-virtualenv'): - self.yum_install('python-virtualenv', check_exit_code=False) - - super(Fedora, self).install_virtualenv() - - def post_process(self): - """Workaround for a bug in eventlet. - - This currently affects RHEL6.1, but the fix can safely be - applied to all RHEL and Fedora distributions. - - This can be removed when the fix is applied upstream. - - Nova: https://bugs.launchpad.net/nova/+bug/884915 - Upstream: https://bitbucket.org/which_linden/eventlet/issue/89 - """ - - # Install "patch" program if it's not there - if not self.check_pkg('patch'): - self.yum_install('patch') - - # Apply the eventlet patch - self.apply_patch(os.path.join(self.venv, 'lib', self.py_version, - 'site-packages', - 'eventlet/green/subprocess.py'), - 'contrib/redhat-eventlet.patch') diff --git a/conductor/tools/pip-requires b/conductor/tools/pip-requires deleted file mode 100644 index ac910b04..00000000 --- a/conductor/tools/pip-requires +++ /dev/null @@ -1,10 +0,0 @@ -anyjson -eventlet>=0.9.12 -jsonpath -puka -Paste -PasteDeploy -iso8601>=0.1.4 -python-heatclient - -http://tarballs.openstack.org/oslo-config/oslo-config-2013.1b4.tar.gz#egg=oslo-config diff --git a/conductor/tools/test-requires b/conductor/tools/test-requires deleted file mode 100644 index d69cfd4c..00000000 --- a/conductor/tools/test-requires +++ /dev/null @@ -1,8 +0,0 @@ -unittest2 -mock==0.8.0 -nose -nose-exclude -nosexcover -#openstack.nose_plugin -pep8==1.0.1 -sphinx>=1.1.2 diff --git a/conductor/tools/with_venv.sh b/conductor/tools/with_venv.sh deleted file mode 100755 index ae91bbcb..00000000 --- a/conductor/tools/with_venv.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -TOOLS=`dirname $0` -VENV=$TOOLS/../.venv -source $VENV/bin/activate && $@ diff --git a/conductor/tox.ini b/conductor/tox.ini deleted file mode 100644 index 9033100e..00000000 --- a/conductor/tox.ini +++ /dev/null @@ -1,46 +0,0 @@ -[tox] -envlist = py27,pep8 - -[testenv] -setenv = VIRTUAL_ENV={envdir} - NOSE_WITH_OPENSTACK=1 - NOSE_OPENSTACK_COLOR=1 - NOSE_OPENSTACK_RED=0.05 - NOSE_OPENSTACK_YELLOW=0.025 - NOSE_OPENSTACK_SHOW_ELAPSED=1 -deps = -r{toxinidir}/tools/pip-requires - -r{toxinidir}/tools/test-requires -commands = nosetests - -[testenv:pep8] -deps = pep8==1.3.3 -commands = pep8 --repeat --show-source conductor setup.py - -[testenv:venv] -commands = {posargs} - -[testenv:cover] -commands = nosetests --cover-erase --cover-package=conductor --with-xcoverage - -[tox:jenkins] -downloadcache = ~/cache/pip - -[testenv:jenkins26] -basepython = python2.6 -setenv = NOSE_WITH_XUNIT=1 -deps = file://{toxinidir}/.cache.bundle - -[testenv:jenkins27] -basepython = python2.7 -setenv = NOSE_WITH_XUNIT=1 -deps = file://{toxinidir}/.cache.bundle - -[testenv:jenkinscover] -deps = file://{toxinidir}/.cache.bundle -setenv = NOSE_WITH_XUNIT=1 -commands = nosetests --cover-erase --cover-package=conductor --with-xcoverage - -[testenv:jenkinsvenv] -deps = file://{toxinidir}/.cache.bundle -setenv = NOSE_WITH_XUNIT=1 -commands = {posargs} diff --git a/dashboard/.gitignore b/dashboard/.gitignore deleted file mode 100644 index 78cafe90..00000000 --- a/dashboard/.gitignore +++ /dev/null @@ -1,19 +0,0 @@ -*.pyc -*.swp -.environment_version -.selenium_log -.coverage* -.noseids -.venv -coverage.xml -pep8.txt -pylint.txt -reports -tabula/local/local_settings.py -/static/ -docs/build/ -docs/source/sourcecode -build -dist -#Autogenerated Documentation -doc/source/api \ No newline at end of file diff --git a/dashboard/README.rst b/dashboard/README.rst deleted file mode 100644 index 150c1b4a..00000000 --- a/dashboard/README.rst +++ /dev/null @@ -1,7 +0,0 @@ -Keero Tabula README -===================== -Tabula is a project that provides Web UI to Keero Project. - -SEE ALSO --------- -* `Keero <http://keero.mirantis.com>`__ diff --git a/dashboard/bin/less/lessc b/dashboard/bin/less/lessc deleted file mode 100755 index 30ae3520..00000000 --- a/dashboard/bin/less/lessc +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/env node - -var path = require('path'), - fs = require('fs'), - sys = require('util'), - os = require('os'); - -var less = require('../lib/less'); -var args = process.argv.slice(1); -var options = { - compress: false, - yuicompress: false, - optimization: 1, - silent: false, - paths: [], - color: true, - strictImports: false -}; - -args = args.filter(function (arg) { - var match; - - if (match = arg.match(/^-I(.+)$/)) { - options.paths.push(match[1]); - return false; - } - - if (match = arg.match(/^--?([a-z][0-9a-z-]*)(?:=([^\s]+))?$/i)) { arg = match[1] } - else { return arg } - - switch (arg) { - case 'v': - case 'version': - sys.puts("lessc " + less.version.join('.') + " (LESS Compiler) [JavaScript]"); - process.exit(0); - case 'verbose': - options.verbose = true; - break; - case 's': - case 'silent': - options.silent = true; - break; - case 'strict-imports': - options.strictImports = true; - break; - case 'h': - case 'help': - sys.puts("usage: lessc source [destination]"); - process.exit(0); - case 'x': - case 'compress': - options.compress = true; - break; - case 'yui-compress': - options.yuicompress = true; - break; - case 'no-color': - options.color = false; - break; - case 'include-path': - options.paths = match[2].split(os.type().match(/Windows/) ? ';' : ':') - .map(function(p) { - if (p) { - return path.resolve(process.cwd(), p); - } - }); - break; - case 'O0': options.optimization = 0; break; - case 'O1': options.optimization = 1; break; - case 'O2': options.optimization = 2; break; - } -}); - -var input = args[1]; -if (input && input != '-') { - input = path.resolve(process.cwd(), input); -} -var output = args[2]; -if (output) { - output = path.resolve(process.cwd(), output); -} - -var css, fd, tree; - -if (! input) { - sys.puts("lessc: no input files"); - process.exit(1); -} - -var parseLessFile = function (e, data) { - if (e) { - sys.puts("lessc: " + e.message); - process.exit(1); - } - - new(less.Parser)({ - paths: [path.dirname(input)].concat(options.paths), - optimization: options.optimization, - filename: input, - strictImports: options.strictImports - }).parse(data, function (err, tree) { - if (err) { - less.writeError(err, options); - process.exit(1); - } else { - try { - css = tree.toCSS({ - compress: options.compress, - yuicompress: options.yuicompress - }); - if (output) { - fd = fs.openSync(output, "w"); - fs.writeSync(fd, css, 0, "utf8"); - } else { - sys.print(css); - } - } catch (e) { - less.writeError(e, options); - process.exit(2); - } - } - }); -}; - -if (input != '-') { - fs.readFile(input, 'utf-8', parseLessFile); -} else { - process.stdin.resume(); - process.stdin.setEncoding('utf8'); - - var buffer = ''; - process.stdin.on('data', function(data) { - buffer += data; - }); - - process.stdin.on('end', function() { - parseLessFile(false, buffer); - }); -} diff --git a/dashboard/bin/lib/less/browser.js b/dashboard/bin/lib/less/browser.js deleted file mode 100644 index cab913be..00000000 --- a/dashboard/bin/lib/less/browser.js +++ /dev/null @@ -1,380 +0,0 @@ -// -// browser.js - client-side engine -// - -var isFileProtocol = (location.protocol === 'file:' || - location.protocol === 'chrome:' || - location.protocol === 'chrome-extension:' || - location.protocol === 'resource:'); - -less.env = less.env || (location.hostname == '127.0.0.1' || - location.hostname == '0.0.0.0' || - location.hostname == 'localhost' || - location.port.length > 0 || - isFileProtocol ? 'development' - : 'production'); - -// Load styles asynchronously (default: false) -// -// This is set to `false` by default, so that the body -// doesn't start loading before the stylesheets are parsed. -// Setting this to `true` can result in flickering. -// -less.async = false; - -// Interval between watch polls -less.poll = less.poll || (isFileProtocol ? 1000 : 1500); - -// -// Watch mode -// -less.watch = function () { return this.watchMode = true }; -less.unwatch = function () { return this.watchMode = false }; - -if (less.env === 'development') { - less.optimization = 0; - - if (/!watch/.test(location.hash)) { - less.watch(); - } - less.watchTimer = setInterval(function () { - if (less.watchMode) { - loadStyleSheets(function (e, root, _, sheet, env) { - if (root) { - createCSS(root.toCSS(), sheet, env.lastModified); - } - }); - } - }, less.poll); -} else { - less.optimization = 3; -} - -var cache; - -try { - cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; -} catch (_) { - cache = null; -} - -// -// Get all <link> tags with the 'rel' attribute set to "stylesheet/less" -// -var links = document.getElementsByTagName('link'); -var typePattern = /^text\/(x-)?less$/; - -less.sheets = []; - -for (var i = 0; i < links.length; i++) { - if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && - (links[i].type.match(typePattern)))) { - less.sheets.push(links[i]); - } -} - - -less.refresh = function (reload) { - var startTime, endTime; - startTime = endTime = new(Date); - - loadStyleSheets(function (e, root, _, sheet, env) { - if (env.local) { - log("loading " + sheet.href + " from cache."); - } else { - log("parsed " + sheet.href + " successfully."); - createCSS(root.toCSS(), sheet, env.lastModified); - } - log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); - (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); - endTime = new(Date); - }, reload); - - loadStyles(); -}; -less.refreshStyles = loadStyles; - -less.refresh(less.env === 'development'); - -function loadStyles() { - var styles = document.getElementsByTagName('style'); - for (var i = 0; i < styles.length; i++) { - if (styles[i].type.match(typePattern)) { - new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { - var css = tree.toCSS(); - var style = styles[i]; - style.type = 'text/css'; - if (style.styleSheet) { - style.styleSheet.cssText = css; - } else { - style.innerHTML = css; - } - }); - } - } -} - -function loadStyleSheets(callback, reload) { - for (var i = 0; i < less.sheets.length; i++) { - loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); - } -} - -function loadStyleSheet(sheet, callback, reload, remaining) { - var url = window.location.href.replace(/[#?].*$/, ''); - var href = sheet.href.replace(/\?.*$/, ''); - var css = cache && cache.getItem(href); - var timestamp = cache && cache.getItem(href + ':timestamp'); - var styles = { css: css, timestamp: timestamp }; - - // Stylesheets in IE don't always return the full path - if (! /^(https?|file):/.test(href)) { - if (href.charAt(0) == "/") { - href = window.location.protocol + "//" + window.location.host + href; - } else { - href = url.slice(0, url.lastIndexOf('/') + 1) + href; - } - } - var filename = href.match(/([^\/]+)$/)[1]; - - xhr(sheet.href, sheet.type, function (data, lastModified) { - if (!reload && styles && lastModified && - (new(Date)(lastModified).valueOf() === - new(Date)(styles.timestamp).valueOf())) { - // Use local copy - createCSS(styles.css, sheet); - callback(null, null, data, sheet, { local: true, remaining: remaining }); - } else { - // Use remote copy (re-parse) - try { - new(less.Parser)({ - optimization: less.optimization, - paths: [href.replace(/[\w\.-]+$/, '')], - mime: sheet.type, - filename: filename - }).parse(data, function (e, root) { - if (e) { return error(e, href) } - try { - callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }); - removeNode(document.getElementById('less-error-message:' + extractId(href))); - } catch (e) { - error(e, href); - } - }); - } catch (e) { - error(e, href); - } - } - }, function (status, url) { - throw new(Error)("Couldn't load " + url + " (" + status + ")"); - }); -} - -function extractId(href) { - return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain - .replace(/^\//, '' ) // Remove root / - .replace(/\?.*$/, '' ) // Remove query - .replace(/\.[^\.\/]+$/, '' ) // Remove file extension - .replace(/[^\.\w-]+/g, '-') // Replace illegal characters - .replace(/\./g, ':'); // Replace dots with colons(for valid id) -} - -function createCSS(styles, sheet, lastModified) { - var css; - - // Strip the query-string - var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; - - // If there is no title set, use the filename, minus the extension - var id = 'less:' + (sheet.title || extractId(href)); - - // If the stylesheet doesn't exist, create a new node - if ((css = document.getElementById(id)) === null) { - css = document.createElement('style'); - css.type = 'text/css'; - css.media = sheet.media || 'screen'; - css.id = id; - document.getElementsByTagName('head')[0].appendChild(css); - } - - if (css.styleSheet) { // IE - try { - css.styleSheet.cssText = styles; - } catch (e) { - throw new(Error)("Couldn't reassign styleSheet.cssText."); - } - } else { - (function (node) { - if (css.childNodes.length > 0) { - if (css.firstChild.nodeValue !== node.nodeValue) { - css.replaceChild(node, css.firstChild); - } - } else { - css.appendChild(node); - } - })(document.createTextNode(styles)); - } - - // Don't update the local store if the file wasn't modified - if (lastModified && cache) { - log('saving ' + href + ' to cache.'); - cache.setItem(href, styles); - cache.setItem(href + ':timestamp', lastModified); - } -} - -function xhr(url, type, callback, errback) { - var xhr = getXMLHttpRequest(); - var async = isFileProtocol ? false : less.async; - - if (typeof(xhr.overrideMimeType) === 'function') { - xhr.overrideMimeType('text/css'); - } - xhr.open('GET', url, async); - xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); - xhr.send(null); - - if (isFileProtocol) { - if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { - callback(xhr.responseText); - } else { - errback(xhr.status, url); - } - } else if (async) { - xhr.onreadystatechange = function () { - if (xhr.readyState == 4) { - handleResponse(xhr, callback, errback); - } - }; - } else { - handleResponse(xhr, callback, errback); - } - - function handleResponse(xhr, callback, errback) { - if (xhr.status >= 200 && xhr.status < 300) { - callback(xhr.responseText, - xhr.getResponseHeader("Last-Modified")); - } else if (typeof(errback) === 'function') { - errback(xhr.status, url); - } - } -} - -function getXMLHttpRequest() { - if (window.XMLHttpRequest) { - return new(XMLHttpRequest); - } else { - try { - return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); - } catch (e) { - log("browser doesn't support AJAX."); - return null; - } - } -} - -function removeNode(node) { - return node && node.parentNode.removeChild(node); -} - -function log(str) { - if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } -} - -function error(e, href) { - var id = 'less-error-message:' + extractId(href); - var template = '<li><label>{line}</label><pre class="{class}">{content}</pre></li>'; - var elem = document.createElement('div'), timer, content, error = []; - var filename = e.filename || href; - - elem.id = id; - elem.className = "less-error-message"; - - content = '<h3>' + (e.message || 'There is an error in your .less file') + - '</h3>' + '<p>in <a href="' + filename + '">' + filename + "</a> "; - - var errorline = function (e, i, classname) { - if (e.extract[i]) { - error.push(template.replace(/\{line\}/, parseInt(e.line) + (i - 1)) - .replace(/\{class\}/, classname) - .replace(/\{content\}/, e.extract[i])); - } - }; - - if (e.stack) { - content += '<br/>' + e.stack.split('\n').slice(1).join('<br/>'); - } else if (e.extract) { - errorline(e, 0, ''); - errorline(e, 1, 'line'); - errorline(e, 2, ''); - content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':</p>' + - '<ul>' + error.join('') + '</ul>'; - } - elem.innerHTML = content; - - // CSS for error messages - createCSS([ - '.less-error-message ul, .less-error-message li {', - 'list-style-type: none;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'margin: 0;', - '}', - '.less-error-message label {', - 'font-size: 12px;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'color: #cc7777;', - '}', - '.less-error-message pre {', - 'color: #dd6666;', - 'padding: 4px 0;', - 'margin: 0;', - 'display: inline-block;', - '}', - '.less-error-message pre.line {', - 'color: #ff0000;', - '}', - '.less-error-message h3 {', - 'font-size: 20px;', - 'font-weight: bold;', - 'padding: 15px 0 5px 0;', - 'margin: 0;', - '}', - '.less-error-message a {', - 'color: #10a', - '}', - '.less-error-message .error {', - 'color: red;', - 'font-weight: bold;', - 'padding-bottom: 2px;', - 'border-bottom: 1px dashed red;', - '}' - ].join('\n'), { title: 'error-message' }); - - elem.style.cssText = [ - "font-family: Arial, sans-serif", - "border: 1px solid #e00", - "background-color: #eee", - "border-radius: 5px", - "-webkit-border-radius: 5px", - "-moz-border-radius: 5px", - "color: #e00", - "padding: 15px", - "margin-bottom: 15px" - ].join(';'); - - if (less.env == 'development') { - timer = setInterval(function () { - if (document.body) { - if (document.getElementById(id)) { - document.body.replaceChild(elem, document.getElementById(id)); - } else { - document.body.insertBefore(elem, document.body.firstChild); - } - clearInterval(timer); - } - }, 10); - } -} - diff --git a/dashboard/bin/lib/less/colors.js b/dashboard/bin/lib/less/colors.js deleted file mode 100644 index ed4c2838..00000000 --- a/dashboard/bin/lib/less/colors.js +++ /dev/null @@ -1,152 +0,0 @@ -(function (tree) { - tree.colors = { - 'aliceblue':'#f0f8ff', - 'antiquewhite':'#faebd7', - 'aqua':'#00ffff', - 'aquamarine':'#7fffd4', - 'azure':'#f0ffff', - 'beige':'#f5f5dc', - 'bisque':'#ffe4c4', - 'black':'#000000', - 'blanchedalmond':'#ffebcd', - 'blue':'#0000ff', - 'blueviolet':'#8a2be2', - 'brown':'#a52a2a', - 'burlywood':'#deb887', - 'cadetblue':'#5f9ea0', - 'chartreuse':'#7fff00', - 'chocolate':'#d2691e', - 'coral':'#ff7f50', - 'cornflowerblue':'#6495ed', - 'cornsilk':'#fff8dc', - 'crimson':'#dc143c', - 'cyan':'#00ffff', - 'darkblue':'#00008b', - 'darkcyan':'#008b8b', - 'darkgoldenrod':'#b8860b', - 'darkgray':'#a9a9a9', - 'darkgrey':'#a9a9a9', - 'darkgreen':'#006400', - 'darkkhaki':'#bdb76b', - 'darkmagenta':'#8b008b', - 'darkolivegreen':'#556b2f', - 'darkorange':'#ff8c00', - 'darkorchid':'#9932cc', - 'darkred':'#8b0000', - 'darksalmon':'#e9967a', - 'darkseagreen':'#8fbc8f', - 'darkslateblue':'#483d8b', - 'darkslategray':'#2f4f4f', - 'darkslategrey':'#2f4f4f', - 'darkturquoise':'#00ced1', - 'darkviolet':'#9400d3', - 'deeppink':'#ff1493', - 'deepskyblue':'#00bfff', - 'dimgray':'#696969', - 'dimgrey':'#696969', - 'dodgerblue':'#1e90ff', - 'firebrick':'#b22222', - 'floralwhite':'#fffaf0', - 'forestgreen':'#228b22', - 'fuchsia':'#ff00ff', - 'gainsboro':'#dcdcdc', - 'ghostwhite':'#f8f8ff', - 'gold':'#ffd700', - 'goldenrod':'#daa520', - 'gray':'#808080', - 'grey':'#808080', - 'green':'#008000', - 'greenyellow':'#adff2f', - 'honeydew':'#f0fff0', - 'hotpink':'#ff69b4', - 'indianred':'#cd5c5c', - 'indigo':'#4b0082', - 'ivory':'#fffff0', - 'khaki':'#f0e68c', - 'lavender':'#e6e6fa', - 'lavenderblush':'#fff0f5', - 'lawngreen':'#7cfc00', - 'lemonchiffon':'#fffacd', - 'lightblue':'#add8e6', - 'lightcoral':'#f08080', - 'lightcyan':'#e0ffff', - 'lightgoldenrodyellow':'#fafad2', - 'lightgray':'#d3d3d3', - 'lightgrey':'#d3d3d3', - 'lightgreen':'#90ee90', - 'lightpink':'#ffb6c1', - 'lightsalmon':'#ffa07a', - 'lightseagreen':'#20b2aa', - 'lightskyblue':'#87cefa', - 'lightslategray':'#778899', - 'lightslategrey':'#778899', - 'lightsteelblue':'#b0c4de', - 'lightyellow':'#ffffe0', - 'lime':'#00ff00', - 'limegreen':'#32cd32', - 'linen':'#faf0e6', - 'magenta':'#ff00ff', - 'maroon':'#800000', - 'mediumaquamarine':'#66cdaa', - 'mediumblue':'#0000cd', - 'mediumorchid':'#ba55d3', - 'mediumpurple':'#9370d8', - 'mediumseagreen':'#3cb371', - 'mediumslateblue':'#7b68ee', - 'mediumspringgreen':'#00fa9a', - 'mediumturquoise':'#48d1cc', - 'mediumvioletred':'#c71585', - 'midnightblue':'#191970', - 'mintcream':'#f5fffa', - 'mistyrose':'#ffe4e1', - 'moccasin':'#ffe4b5', - 'navajowhite':'#ffdead', - 'navy':'#000080', - 'oldlace':'#fdf5e6', - 'olive':'#808000', - 'olivedrab':'#6b8e23', - 'orange':'#ffa500', - 'orangered':'#ff4500', - 'orchid':'#da70d6', - 'palegoldenrod':'#eee8aa', - 'palegreen':'#98fb98', - 'paleturquoise':'#afeeee', - 'palevioletred':'#d87093', - 'papayawhip':'#ffefd5', - 'peachpuff':'#ffdab9', - 'peru':'#cd853f', - 'pink':'#ffc0cb', - 'plum':'#dda0dd', - 'powderblue':'#b0e0e6', - 'purple':'#800080', - 'red':'#ff0000', - 'rosybrown':'#bc8f8f', - 'royalblue':'#4169e1', - 'saddlebrown':'#8b4513', - 'salmon':'#fa8072', - 'sandybrown':'#f4a460', - 'seagreen':'#2e8b57', - 'seashell':'#fff5ee', - 'sienna':'#a0522d', - 'silver':'#c0c0c0', - 'skyblue':'#87ceeb', - 'slateblue':'#6a5acd', - 'slategray':'#708090', - 'slategrey':'#708090', - 'snow':'#fffafa', - 'springgreen':'#00ff7f', - 'steelblue':'#4682b4', - 'tan':'#d2b48c', - 'teal':'#008080', - 'thistle':'#d8bfd8', - 'tomato':'#ff6347', - 'transparent':'rgba(0,0,0,0)', - 'turquoise':'#40e0d0', - 'violet':'#ee82ee', - 'wheat':'#f5deb3', - 'white':'#ffffff', - 'whitesmoke':'#f5f5f5', - 'yellow':'#ffff00', - 'yellowgreen':'#9acd32' - }; -})(require('./tree')); diff --git a/dashboard/bin/lib/less/cssmin.js b/dashboard/bin/lib/less/cssmin.js deleted file mode 100644 index 427de71c..00000000 --- a/dashboard/bin/lib/less/cssmin.js +++ /dev/null @@ -1,355 +0,0 @@ -/** - * cssmin.js - * Author: Stoyan Stefanov - http://phpied.com/ - * This is a JavaScript port of the CSS minification tool - * distributed with YUICompressor, itself a port - * of the cssmin utility by Isaac Schlueter - http://foohack.com/ - * Permission is hereby granted to use the JavaScript version under the same - * conditions as the YUICompressor (original YUICompressor note below). - */ - -/* -* YUI Compressor -* http://developer.yahoo.com/yui/compressor/ -* Author: Julien Lecomte - http://www.julienlecomte.net/ -* Copyright (c) 2011 Yahoo! Inc. All rights reserved. -* The copyrights embodied in the content of this file are licensed -* by Yahoo! Inc. under the BSD (revised) open source license. -*/ -var YAHOO = YAHOO || {}; -YAHOO.compressor = YAHOO.compressor || {}; - -/** - * Utility method to replace all data urls with tokens before we start - * compressing, to avoid performance issues running some of the subsequent - * regexes against large strings chunks. - * - * @private - * @method _extractDataUrls - * @param {String} css The input css - * @param {Array} The global array of tokens to preserve - * @returns String The processed css - */ -YAHOO.compressor._extractDataUrls = function (css, preservedTokens) { - - // Leave data urls alone to increase parse performance. - var maxIndex = css.length - 1, - appendIndex = 0, - startIndex, - endIndex, - terminator, - foundTerminator, - sb = [], - m, - preserver, - token, - pattern = /url\(\s*(["']?)data\:/g; - - // Since we need to account for non-base64 data urls, we need to handle - // ' and ) being part of the data string. Hence switching to indexOf, - // to determine whether or not we have matching string terminators and - // handling sb appends directly, instead of using matcher.append* methods. - - while ((m = pattern.exec(css)) !== null) { - - startIndex = m.index + 4; // "url(".length() - terminator = m[1]; // ', " or empty (not quoted) - - if (terminator.length === 0) { - terminator = ")"; - } - - foundTerminator = false; - - endIndex = pattern.lastIndex - 1; - - while(foundTerminator === false && endIndex+1 <= maxIndex) { - endIndex = css.indexOf(terminator, endIndex + 1); - - // endIndex == 0 doesn't really apply here - if ((endIndex > 0) && (css.charAt(endIndex - 1) !== '\\')) { - foundTerminator = true; - if (")" != terminator) { - endIndex = css.indexOf(")", endIndex); - } - } - } - - // Enough searching, start moving stuff over to the buffer - sb.push(css.substring(appendIndex, m.index)); - - if (foundTerminator) { - token = css.substring(startIndex, endIndex); - token = token.replace(/\s+/g, ""); - preservedTokens.push(token); - - preserver = "url(___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___)"; - sb.push(preserver); - - appendIndex = endIndex + 1; - } else { - // No end terminator found, re-add the whole match. Should we throw/warn here? - sb.push(css.substring(m.index, pattern.lastIndex)); - appendIndex = pattern.lastIndex; - } - } - - sb.push(css.substring(appendIndex)); - - return sb.join(""); -}; - -/** - * Utility method to compress hex color values of the form #AABBCC to #ABC. - * - * DOES NOT compress CSS ID selectors which match the above pattern (which would break things). - * e.g. #AddressForm { ... } - * - * DOES NOT compress IE filters, which have hex color values (which would break things). - * e.g. filter: chroma(color="#FFFFFF"); - * - * DOES NOT compress invalid hex values. - * e.g. background-color: #aabbccdd - * - * @private - * @method _compressHexColors - * @param {String} css The input css - * @returns String The processed css - */ -YAHOO.compressor._compressHexColors = function(css) { - - // Look for hex colors inside { ... } (to avoid IDs) and which don't have a =, or a " in front of them (to avoid filters) - var pattern = /(\=\s*?["']?)?#([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])(\}|[^0-9a-f{][^{]*?\})/gi, - m, - index = 0, - isFilter, - sb = []; - - while ((m = pattern.exec(css)) !== null) { - - sb.push(css.substring(index, m.index)); - - isFilter = m[1]; - - if (isFilter) { - // Restore, maintain case, otherwise filter will break - sb.push(m[1] + "#" + (m[2] + m[3] + m[4] + m[5] + m[6] + m[7])); - } else { - if (m[2].toLowerCase() == m[3].toLowerCase() && - m[4].toLowerCase() == m[5].toLowerCase() && - m[6].toLowerCase() == m[7].toLowerCase()) { - - // Compress. - sb.push("#" + (m[3] + m[5] + m[7]).toLowerCase()); - } else { - // Non compressible color, restore but lower case. - sb.push("#" + (m[2] + m[3] + m[4] + m[5] + m[6] + m[7]).toLowerCase()); - } - } - - index = pattern.lastIndex = pattern.lastIndex - m[8].length; - } - - sb.push(css.substring(index)); - - return sb.join(""); -}; - -YAHOO.compressor.cssmin = function (css, linebreakpos) { - - var startIndex = 0, - endIndex = 0, - i = 0, max = 0, - preservedTokens = [], - comments = [], - token = '', - totallen = css.length, - placeholder = ''; - - css = this._extractDataUrls(css, preservedTokens); - - // collect all comment blocks... - while ((startIndex = css.indexOf("/*", startIndex)) >= 0) { - endIndex = css.indexOf("*/", startIndex + 2); - if (endIndex < 0) { - endIndex = totallen; - } - token = css.slice(startIndex + 2, endIndex); - comments.push(token); - css = css.slice(0, startIndex + 2) + "___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + (comments.length - 1) + "___" + css.slice(endIndex); - startIndex += 2; - } - - // preserve strings so their content doesn't get accidentally minified - css = css.replace(/("([^\\"]|\\.|\\)*")|('([^\\']|\\.|\\)*')/g, function (match) { - var i, max, quote = match.substring(0, 1); - - match = match.slice(1, -1); - - // maybe the string contains a comment-like substring? - // one, maybe more? put'em back then - if (match.indexOf("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_") >= 0) { - for (i = 0, max = comments.length; i < max; i = i + 1) { - match = match.replace("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___", comments[i]); - } - } - - // minify alpha opacity in filter strings - match = match.replace(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/gi, "alpha(opacity="); - - preservedTokens.push(match); - return quote + "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___" + quote; - }); - - // strings are safe, now wrestle the comments - for (i = 0, max = comments.length; i < max; i = i + 1) { - - token = comments[i]; - placeholder = "___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___"; - - // ! in the first position of the comment means preserve - // so push to the preserved tokens keeping the ! - if (token.charAt(0) === "!") { - preservedTokens.push(token); - css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"); - continue; - } - - // \ in the last position looks like hack for Mac/IE5 - // shorten that to /*\*/ and the next one to /**/ - if (token.charAt(token.length - 1) === "\\") { - preservedTokens.push("\\"); - css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"); - i = i + 1; // attn: advancing the loop - preservedTokens.push(""); - css = css.replace("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___", "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"); - continue; - } - - // keep empty comments after child selectors (IE7 hack) - // e.g. html >/**/ body - if (token.length === 0) { - startIndex = css.indexOf(placeholder); - if (startIndex > 2) { - if (css.charAt(startIndex - 3) === '>') { - preservedTokens.push(""); - css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"); - } - } - } - - // in all other cases kill the comment - css = css.replace("/*" + placeholder + "*/", ""); - } - - - // Normalize all whitespace strings to single spaces. Easier to work with that way. - css = css.replace(/\s+/g, " "); - - // Remove the spaces before the things that should not have spaces before them. - // But, be careful not to turn "p :link {...}" into "p:link{...}" - // Swap out any pseudo-class colons with the token, and then swap back. - css = css.replace(/(^|\})(([^\{:])+:)+([^\{]*\{)/g, function (m) { - return m.replace(":", "___YUICSSMIN_PSEUDOCLASSCOLON___"); - }); - css = css.replace(/\s+([!{};:>+\(\)\],])/g, '$1'); - css = css.replace(/___YUICSSMIN_PSEUDOCLASSCOLON___/g, ":"); - - // retain space for special IE6 cases - css = css.replace(/:first-(line|letter)(\{|,)/g, ":first-$1 $2"); - - // no space after the end of a preserved comment - css = css.replace(/\*\/ /g, '*/'); - - - // If there is a @charset, then only allow one, and push to the top of the file. - css = css.replace(/^(.*)(@charset "[^"]*";)/gi, '$2$1'); - css = css.replace(/^(\s*@charset [^;]+;\s*)+/gi, '$1'); - - // Put the space back in some cases, to support stuff like - // @media screen and (-webkit-min-device-pixel-ratio:0){ - css = css.replace(/\band\(/gi, "and ("); - - - // Remove the spaces after the things that should not have spaces after them. - css = css.replace(/([!{}:;>+\(\[,])\s+/g, '$1'); - - // remove unnecessary semicolons - css = css.replace(/;+\}/g, "}"); - - // Replace 0(px,em,%) with 0. - css = css.replace(/([\s:])(0)(px|em|%|in|cm|mm|pc|pt|ex)/gi, "$1$2"); - - // Replace 0 0 0 0; with 0. - css = css.replace(/:0 0 0 0(;|\})/g, ":0$1"); - css = css.replace(/:0 0 0(;|\})/g, ":0$1"); - css = css.replace(/:0 0(;|\})/g, ":0$1"); - - // Replace background-position:0; with background-position:0 0; - // same for transform-origin - css = css.replace(/(background-position|transform-origin|webkit-transform-origin|moz-transform-origin|o-transform-origin|ms-transform-origin):0(;|\})/gi, function(all, prop, tail) { - return prop.toLowerCase() + ":0 0" + tail; - }); - - // Replace 0.6 to .6, but only when preceded by : or a white-space - css = css.replace(/(:|\s)0+\.(\d+)/g, "$1.$2"); - - // Shorten colors from rgb(51,102,153) to #336699 - // This makes it more likely that it'll get further compressed in the next step. - css = css.replace(/rgb\s*\(\s*([0-9,\s]+)\s*\)/gi, function () { - var i, rgbcolors = arguments[1].split(','); - for (i = 0; i < rgbcolors.length; i = i + 1) { - rgbcolors[i] = parseInt(rgbcolors[i], 10).toString(16); - if (rgbcolors[i].length === 1) { - rgbcolors[i] = '0' + rgbcolors[i]; - } - } - return '#' + rgbcolors.join(''); - }); - - // Shorten colors from #AABBCC to #ABC. - css = this._compressHexColors(css); - - // border: none -> border:0 - css = css.replace(/(border|border-top|border-right|border-bottom|border-right|outline|background):none(;|\})/gi, function(all, prop, tail) { - return prop.toLowerCase() + ":0" + tail; - }); - - // shorter opacity IE filter - css = css.replace(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/gi, "alpha(opacity="); - - // Remove empty rules. - css = css.replace(/[^\};\{\/]+\{\}/g, ""); - - if (linebreakpos >= 0) { - // Some source control tools don't like it when files containing lines longer - // than, say 8000 characters, are checked in. The linebreak option is used in - // that case to split long lines after a specific column. - startIndex = 0; - i = 0; - while (i < css.length) { - i = i + 1; - if (css[i - 1] === '}' && i - startIndex > linebreakpos) { - css = css.slice(0, i) + '\n' + css.slice(i); - startIndex = i; - } - } - } - - // Replace multiple semi-colons in a row by a single one - // See SF bug #1980989 - css = css.replace(/;;+/g, ";"); - - // restore preserved comments and strings - for (i = 0, max = preservedTokens.length; i < max; i = i + 1) { - css = css.replace("___YUICSSMIN_PRESERVED_TOKEN_" + i + "___", preservedTokens[i]); - } - - // Trim the final string (for any leading or trailing white spaces) - css = css.replace(/^\s+|\s+$/g, ""); - - return css; - -}; - -exports.compressor = YAHOO.compressor; diff --git a/dashboard/bin/lib/less/functions.js b/dashboard/bin/lib/less/functions.js deleted file mode 100644 index 6eb34bac..00000000 --- a/dashboard/bin/lib/less/functions.js +++ /dev/null @@ -1,228 +0,0 @@ -(function (tree) { - -tree.functions = { - rgb: function (r, g, b) { - return this.rgba(r, g, b, 1.0); - }, - rgba: function (r, g, b, a) { - var rgb = [r, g, b].map(function (c) { return number(c) }), - a = number(a); - return new(tree.Color)(rgb, a); - }, - hsl: function (h, s, l) { - return this.hsla(h, s, l, 1.0); - }, - hsla: function (h, s, l, a) { - h = (number(h) % 360) / 360; - s = number(s); l = number(l); a = number(a); - - var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; - var m1 = l * 2 - m2; - - return this.rgba(hue(h + 1/3) * 255, - hue(h) * 255, - hue(h - 1/3) * 255, - a); - - function hue(h) { - h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - else if (h * 2 < 1) return m2; - else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; - else return m1; - } - }, - hue: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().h)); - }, - saturation: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); - }, - lightness: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); - }, - alpha: function (color) { - return new(tree.Dimension)(color.toHSL().a); - }, - saturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s += amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - desaturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s -= amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - lighten: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l += amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - darken: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l -= amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - fadein: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a += amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fadeout: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a -= amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fade: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a = amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - spin: function (color, amount) { - var hsl = color.toHSL(); - var hue = (hsl.h + amount.value) % 360; - - hsl.h = hue < 0 ? 360 + hue : hue; - - return hsla(hsl); - }, - // - // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein - // http://sass-lang.com - // - mix: function (color1, color2, weight) { - var p = weight.value / 100.0; - var w = p * 2 - 1; - var a = color1.toHSL().a - color2.toHSL().a; - - var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; - - var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, - color1.rgb[1] * w1 + color2.rgb[1] * w2, - color1.rgb[2] * w1 + color2.rgb[2] * w2]; - - var alpha = color1.alpha * p + color2.alpha * (1 - p); - - return new(tree.Color)(rgb, alpha); - }, - greyscale: function (color) { - return this.desaturate(color, new(tree.Dimension)(100)); - }, - e: function (str) { - return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); - }, - escape: function (str) { - return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); - }, - '%': function (quoted /* arg, arg, ...*/) { - var args = Array.prototype.slice.call(arguments, 1), - str = quoted.value; - - for (var i = 0; i < args.length; i++) { - str = str.replace(/%[sda]/i, function(token) { - var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); - return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; - }); - } - str = str.replace(/%%/g, '%'); - return new(tree.Quoted)('"' + str + '"', str); - }, - round: function (n) { - return this._math('round', n); - }, - ceil: function (n) { - return this._math('ceil', n); - }, - floor: function (n) { - return this._math('floor', n); - }, - _math: function (fn, n) { - if (n instanceof tree.Dimension) { - return new(tree.Dimension)(Math[fn](number(n)), n.unit); - } else if (typeof(n) === 'number') { - return Math[fn](n); - } else { - throw { type: "Argument", message: "argument must be a number" }; - } - }, - argb: function (color) { - return new(tree.Anonymous)(color.toARGB()); - - }, - percentage: function (n) { - return new(tree.Dimension)(n.value * 100, '%'); - }, - color: function (n) { - if (n instanceof tree.Quoted) { - return new(tree.Color)(n.value.slice(1)); - } else { - throw { type: "Argument", message: "argument must be a string" }; - } - }, - iscolor: function (n) { - return this._isa(n, tree.Color); - }, - isnumber: function (n) { - return this._isa(n, tree.Dimension); - }, - isstring: function (n) { - return this._isa(n, tree.Quoted); - }, - iskeyword: function (n) { - return this._isa(n, tree.Keyword); - }, - isurl: function (n) { - return this._isa(n, tree.URL); - }, - ispixel: function (n) { - return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; - }, - ispercentage: function (n) { - return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; - }, - isem: function (n) { - return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; - }, - _isa: function (n, Type) { - return (n instanceof Type) ? tree.True : tree.False; - } -}; - -function hsla(hsla) { - return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); -} - -function number(n) { - if (n instanceof tree.Dimension) { - return parseFloat(n.unit == '%' ? n.value / 100 : n.value); - } else if (typeof(n) === 'number') { - return n; - } else { - throw { - error: "RuntimeError", - message: "color functions take numbers as parameters" - }; - } -} - -function clamp(val) { - return Math.min(1, Math.max(0, val)); -} - -})(require('./tree')); diff --git a/dashboard/bin/lib/less/index.js b/dashboard/bin/lib/less/index.js deleted file mode 100644 index a11fa998..00000000 --- a/dashboard/bin/lib/less/index.js +++ /dev/null @@ -1,148 +0,0 @@ -var path = require('path'), - sys = require('util'), - fs = require('fs'); - -var less = { - version: [1, 3, 0], - Parser: require('./parser').Parser, - importer: require('./parser').importer, - tree: require('./tree'), - render: function (input, options, callback) { - options = options || {}; - - if (typeof(options) === 'function') { - callback = options, options = {}; - } - - var parser = new(less.Parser)(options), - ee; - - if (callback) { - parser.parse(input, function (e, root) { - callback(e, root && root.toCSS && root.toCSS(options)); - }); - } else { - ee = new(require('events').EventEmitter); - - process.nextTick(function () { - parser.parse(input, function (e, root) { - if (e) { ee.emit('error', e) } - else { ee.emit('success', root.toCSS(options)) } - }); - }); - return ee; - } - }, - writeError: function (ctx, options) { - options = options || {}; - - var message = ""; - var extract = ctx.extract; - var error = []; - var stylize = options.color ? less.stylize : function (str) { return str }; - - if (options.silent) { return } - - if (ctx.stack) { return sys.error(stylize(ctx.stack, 'red')) } - - if (!ctx.hasOwnProperty('index')) { - return sys.error(ctx.stack || ctx.message); - } - - if (typeof(extract[0]) === 'string') { - error.push(stylize((ctx.line - 1) + ' ' + extract[0], 'grey')); - } - - if (extract[1]) { - error.push(ctx.line + ' ' + extract[1].slice(0, ctx.column) - + stylize(stylize(stylize(extract[1][ctx.column], 'bold') - + extract[1].slice(ctx.column + 1), 'red'), 'inverse')); - } - - if (typeof(extract[2]) === 'string') { - error.push(stylize((ctx.line + 1) + ' ' + extract[2], 'grey')); - } - error = error.join('\n') + '\033[0m\n'; - - message += stylize(ctx.type + 'Error: ' + ctx.message, 'red'); - ctx.filename && (message += stylize(' in ', 'red') + ctx.filename + - stylize(':' + ctx.line + ':' + ctx.column, 'grey')); - - sys.error(message, error); - - if (ctx.callLine) { - sys.error(stylize('from ', 'red') + (ctx.filename || '')); - sys.error(stylize(ctx.callLine, 'grey') + ' ' + ctx.callExtract); - } - } -}; - -['color', 'directive', 'operation', 'dimension', - 'keyword', 'variable', 'ruleset', 'element', - 'selector', 'quoted', 'expression', 'rule', - 'call', 'url', 'alpha', 'import', - 'mixin', 'comment', 'anonymous', 'value', - 'javascript', 'assignment', 'condition', 'paren', - 'media' -].forEach(function (n) { - require('./tree/' + n); -}); - -less.Parser.importer = function (file, paths, callback, env) { - var pathname; - - // TODO: Undo this at some point, - // or use different approach. - paths.unshift('.'); - - for (var i = 0; i < paths.length; i++) { - try { - pathname = path.join(paths[i], file); - fs.statSync(pathname); - break; - } catch (e) { - pathname = null; - } - } - - if (pathname) { - fs.readFile(pathname, 'utf-8', function(e, data) { - if (e) return callback(e); - - new(less.Parser)({ - paths: [path.dirname(pathname)].concat(paths), - filename: pathname - }).parse(data, function (e, root) { - callback(e, root, data); - }); - }); - } else { - if (typeof(env.errback) === "function") { - env.errback(file, paths, callback); - } else { - callback({ type: 'File', message: "'" + file + "' wasn't found.\n" }); - } - } -} - -require('./functions'); -require('./colors'); - -for (var k in less) { exports[k] = less[k] } - -// Stylize a string -function stylize(str, style) { - var styles = { - 'bold' : [1, 22], - 'inverse' : [7, 27], - 'underline' : [4, 24], - 'yellow' : [33, 39], - 'green' : [32, 39], - 'red' : [31, 39], - 'grey' : [90, 39] - }; - return '\033[' + styles[style][0] + 'm' + str + - '\033[' + styles[style][1] + 'm'; -} -less.stylize = stylize; - diff --git a/dashboard/bin/lib/less/parser.js b/dashboard/bin/lib/less/parser.js deleted file mode 100644 index d732e1b1..00000000 --- a/dashboard/bin/lib/less/parser.js +++ /dev/null @@ -1,1334 +0,0 @@ -var less, tree; - -if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { - // Rhino - // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 - if (typeof(window) === 'undefined') { less = {} } - else { less = window.less = {} } - tree = less.tree = {}; - less.mode = 'rhino'; -} else if (typeof(window) === 'undefined') { - // Node.js - less = exports, - tree = require('./tree'); - less.mode = 'node'; -} else { - // Browser - if (typeof(window.less) === 'undefined') { window.less = {} } - less = window.less, - tree = window.less.tree = {}; - less.mode = 'browser'; -} -// -// less.js - parser -// -// A relatively straight-forward predictive parser. -// There is no tokenization/lexing stage, the input is parsed -// in one sweep. -// -// To make the parser fast enough to run in the browser, several -// optimization had to be made: -// -// - Matching and slicing on a huge input is often cause of slowdowns. -// The solution is to chunkify the input into smaller strings. -// The chunks are stored in the `chunks` var, -// `j` holds the current chunk index, and `current` holds -// the index of the current chunk in relation to `input`. -// This gives us an almost 4x speed-up. -// -// - In many cases, we don't need to match individual tokens; -// for example, if a value doesn't hold any variables, operations -// or dynamic references, the parser can effectively 'skip' it, -// treating it as a literal. -// An example would be '1px solid #000' - which evaluates to itself, -// we don't need to know what the individual components are. -// The drawback, of course is that you don't get the benefits of -// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, -// and a smaller speed-up in the code-gen. -// -// -// Token matching is done with the `$` function, which either takes -// a terminal string or regexp, or a non-terminal function to call. -// It also takes care of moving all the indices forwards. -// -// -less.Parser = function Parser(env) { - var input, // LeSS input string - i, // current index in `input` - j, // current chunk - temp, // temporarily holds a chunk's state, for backtracking - memo, // temporarily holds `i`, when backtracking - furthest, // furthest index the parser has gone to - chunks, // chunkified input - current, // index of current chunk, in `input` - parser; - - var that = this; - - // This function is called after all files - // have been imported through `@import`. - var finish = function () {}; - - var imports = this.imports = { - paths: env && env.paths || [], // Search paths, when importing - queue: [], // Files which haven't been imported yet - files: {}, // Holds the imported parse trees - contents: {}, // Holds the imported file contents - mime: env && env.mime, // MIME type of .less files - error: null, // Error in parsing/evaluating an import - push: function (path, callback) { - var that = this; - this.queue.push(path); - - // - // Import a file asynchronously - // - less.Parser.importer(path, this.paths, function (e, root, contents) { - that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue - - var imported = path in that.files; - - that.files[path] = root; // Store the root - that.contents[path] = contents; - - if (e && !that.error) { that.error = e } - - callback(e, root, imported); - - if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing - }, env); - } - }; - - function save() { temp = chunks[j], memo = i, current = i } - function restore() { chunks[j] = temp, i = memo, current = i } - - function sync() { - if (i > current) { - chunks[j] = chunks[j].slice(i - current); - current = i; - } - } - // - // Parse from a token, regexp or string, and move forward if match - // - function $(tok) { - var match, args, length, c, index, endIndex, k, mem; - - // - // Non-terminal - // - if (tok instanceof Function) { - return tok.call(parser.parsers); - // - // Terminal - // - // Either match a single character in the input, - // or match a regexp in the current chunk (chunk[j]). - // - } else if (typeof(tok) === 'string') { - match = input.charAt(i) === tok ? tok : null; - length = 1; - sync (); - } else { - sync (); - - if (match = tok.exec(chunks[j])) { - length = match[0].length; - } else { - return null; - } - } - - // The match is confirmed, add the match length to `i`, - // and consume any extra white-space characters (' ' || '\n') - // which come after that. The reason for this is that LeSS's - // grammar is mostly white-space insensitive. - // - if (match) { - mem = i += length; - endIndex = i + chunks[j].length - length; - - while (i < endIndex) { - c = input.charCodeAt(i); - if (! (c === 32 || c === 10 || c === 9)) { break } - i++; - } - chunks[j] = chunks[j].slice(length + (i - mem)); - current = i; - - if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } - - if(typeof(match) === 'string') { - return match; - } else { - return match.length === 1 ? match[0] : match; - } - } - } - - function expect(arg, msg) { - var result = $(arg); - if (! result) { - error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" - : "unexpected token")); - } else { - return result; - } - } - - function error(msg, type) { - throw { index: i, type: type || 'Syntax', message: msg }; - } - - // Same as $(), but don't change the state of the parser, - // just return the match. - function peek(tok) { - if (typeof(tok) === 'string') { - return input.charAt(i) === tok; - } else { - if (tok.test(chunks[j])) { - return true; - } else { - return false; - } - } - } - - function basename(pathname) { - if (less.mode === 'node') { - return require('path').basename(pathname); - } else { - return pathname.match(/[^\/]+$/)[0]; - } - } - - function getInput(e, env) { - if (e.filename && env.filename && (e.filename !== env.filename)) { - return parser.imports.contents[basename(e.filename)]; - } else { - return input; - } - } - - function getLocation(index, input) { - for (var n = index, column = -1; - n >= 0 && input.charAt(n) !== '\n'; - n--) { column++ } - - return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, - column: column }; - } - - function LessError(e, env) { - var input = getInput(e, env), - loc = getLocation(e.index, input), - line = loc.line, - col = loc.column, - lines = input.split('\n'); - - this.type = e.type || 'Syntax'; - this.message = e.message; - this.filename = e.filename || env.filename; - this.index = e.index; - this.line = typeof(line) === 'number' ? line + 1 : null; - this.callLine = e.call && (getLocation(e.call, input).line + 1); - this.callExtract = lines[getLocation(e.call, input).line]; - this.stack = e.stack; - this.column = col; - this.extract = [ - lines[line - 1], - lines[line], - lines[line + 1] - ]; - } - - this.env = env = env || {}; - - // The optimization level dictates the thoroughness of the parser, - // the lower the number, the less nodes it will create in the tree. - // This could matter for debugging, or if you want to access - // the individual nodes in the tree. - this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; - - this.env.filename = this.env.filename || null; - - // - // The Parser - // - return parser = { - - imports: imports, - // - // Parse an input string into an abstract syntax tree, - // call `callback` when done. - // - parse: function (str, callback) { - var root, start, end, zone, line, lines, buff = [], c, error = null; - - i = j = current = furthest = 0; - input = str.replace(/\r\n/g, '\n'); - - // Split the input into chunks. - chunks = (function (chunks) { - var j = 0, - skip = /[^"'`\{\}\/\(\)\\]+/g, - comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, - string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`\\\r\n]|\\.)*)`/g, - level = 0, - match, - chunk = chunks[0], - inParam; - - for (var i = 0, c, cc; i < input.length; i++) { - skip.lastIndex = i; - if (match = skip.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - } - } - c = input.charAt(i); - comment.lastIndex = string.lastIndex = i; - - if (match = string.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - - if (!inParam && c === '/') { - cc = input.charAt(i + 1); - if (cc === '/' || cc === '*') { - if (match = comment.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - } - } - - switch (c) { - case '{': if (! inParam) { level ++; chunk.push(c); break } - case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } - case '(': if (! inParam) { inParam = true; chunk.push(c); break } - case ')': if ( inParam) { inParam = false; chunk.push(c); break } - default: chunk.push(c); - } - } - if (level > 0) { - error = new(LessError)({ - index: i, - type: 'Parse', - message: "missing closing `}`", - filename: env.filename - }, env); - } - - return chunks.map(function (c) { return c.join('') });; - })([[]]); - - if (error) { - return callback(error); - } - - // Start with the primary rule. - // The whole syntax tree is held under a Ruleset node, - // with the `root` property set to true, so no `{}` are - // output. The callback is called when the input is parsed. - try { - root = new(tree.Ruleset)([], $(this.parsers.primary)); - root.root = true; - } catch (e) { - return callback(new(LessError)(e, env)); - } - - root.toCSS = (function (evaluate) { - var line, lines, column; - - return function (options, variables) { - var frames = [], importError; - - options = options || {}; - // - // Allows setting variables with a hash, so: - // - // `{ color: new(tree.Color)('#f01') }` will become: - // - // new(tree.Rule)('@color', - // new(tree.Value)([ - // new(tree.Expression)([ - // new(tree.Color)('#f01') - // ]) - // ]) - // ) - // - if (typeof(variables) === 'object' && !Array.isArray(variables)) { - variables = Object.keys(variables).map(function (k) { - var value = variables[k]; - - if (! (value instanceof tree.Value)) { - if (! (value instanceof tree.Expression)) { - value = new(tree.Expression)([value]); - } - value = new(tree.Value)([value]); - } - return new(tree.Rule)('@' + k, value, false, 0); - }); - frames = [new(tree.Ruleset)(null, variables)]; - } - - try { - var css = evaluate.call(this, { frames: frames }) - .toCSS([], { compress: options.compress || false }); - } catch (e) { - throw new(LessError)(e, env); - } - - if ((importError = parser.imports.error)) { // Check if there was an error during importing - if (importError instanceof LessError) throw importError; - else throw new(LessError)(importError, env); - } - - if (options.yuicompress && less.mode === 'node') { - return require('./cssmin').compressor.cssmin(css); - } else if (options.compress) { - return css.replace(/(\s)+/g, "$1"); - } else { - return css; - } - }; - })(root.eval); - - // If `i` is smaller than the `input.length - 1`, - // it means the parser wasn't able to parse the whole - // string, so we've got a parsing error. - // - // We try to extract a \n delimited string, - // showing the line where the parse error occured. - // We split it up into two parts (the part which parsed, - // and the part which didn't), so we can color them differently. - if (i < input.length - 1) { - i = furthest; - lines = input.split('\n'); - line = (input.slice(0, i).match(/\n/g) || "").length + 1; - - for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } - - error = { - type: "Parse", - message: "Syntax Error on line " + line, - index: i, - filename: env.filename, - line: line, - column: column, - extract: [ - lines[line - 2], - lines[line - 1], - lines[line] - ] - }; - } - - if (this.imports.queue.length > 0) { - finish = function () { callback(error, root) }; - } else { - callback(error, root); - } - }, - - // - // Here in, the parsing rules/functions - // - // The basic structure of the syntax tree generated is as follows: - // - // Ruleset -> Rule -> Value -> Expression -> Entity - // - // Here's some LESS code: - // - // .class { - // color: #fff; - // border: 1px solid #000; - // width: @w + 4px; - // > .child {...} - // } - // - // And here's what the parse tree might look like: - // - // Ruleset (Selector '.class', [ - // Rule ("color", Value ([Expression [Color #fff]])) - // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) - // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) - // Ruleset (Selector [Element '>', '.child'], [...]) - // ]) - // - // In general, most rules will try to parse a token with the `$()` function, and if the return - // value is truly, will return a new node, of the relevant type. Sometimes, we need to check - // first, before parsing, that's when we use `peek()`. - // - parsers: { - // - // The `primary` rule is the *entry* and *exit* point of the parser. - // The rules here can appear at any level of the parse tree. - // - // The recursive nature of the grammar is an interplay between the `block` - // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, - // as represented by this simplified grammar: - // - // primary → (ruleset | rule)+ - // ruleset → selector+ block - // block → '{' primary '}' - // - // Only at one point is the primary rule not called from the - // block rule: at the root level. - // - primary: function () { - var node, root = []; - - while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || - $(this.mixin.call) || $(this.comment) || $(this.directive)) - || $(/^[\s\n]+/)) { - node && root.push(node); - } - return root; - }, - - // We create a Comment node for CSS comments `/* */`, - // but keep the LeSS comments `//` silent, by just skipping - // over them. - comment: function () { - var comment; - - if (input.charAt(i) !== '/') return; - - if (input.charAt(i + 1) === '/') { - return new(tree.Comment)($(/^\/\/.*/), true); - } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { - return new(tree.Comment)(comment); - } - }, - - // - // Entities are tokens which can be found inside an Expression - // - entities: { - // - // A string, which supports escaping " and ' - // - // "milky way" 'he\'s the one!' - // - quoted: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; - - e && $('~'); - - if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { - return new(tree.Quoted)(str[0], str[1] || str[2], e); - } - }, - - // - // A catch-all word, such as: - // - // black border-collapse - // - keyword: function () { - var k; - - if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { - if (tree.colors.hasOwnProperty(k)) { - // detect named color - return new(tree.Color)(tree.colors[k].slice(1)); - } else { - return new(tree.Keyword)(k); - } - } - }, - - // - // A function call - // - // rgb(255, 0, 255) - // - // We also try to catch IE's `alpha()`, but let the `alpha` parser - // deal with the details. - // - // The arguments are parsed with the `entities.arguments` parser. - // - call: function () { - var name, args, index = i; - - if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; - - name = name[1].toLowerCase(); - - if (name === 'url') { return null } - else { i += name.length } - - if (name === 'alpha') { return $(this.alpha) } - - $('('); // Parse the '(' and consume whitespace. - - args = $(this.entities.arguments); - - if (! $(')')) return; - - if (name) { return new(tree.Call)(name, args, index, env.filename) } - }, - arguments: function () { - var args = [], arg; - - while (arg = $(this.entities.assignment) || $(this.expression)) { - args.push(arg); - if (! $(',')) { break } - } - return args; - }, - literal: function () { - return $(this.entities.dimension) || - $(this.entities.color) || - $(this.entities.quoted); - }, - - // Assignments are argument entities for calls. - // They are present in ie filter properties as shown below. - // - // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) - // - - assignment: function () { - var key, value; - if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { - return new(tree.Assignment)(key, value); - } - }, - - // - // Parse url() tokens - // - // We use a specific rule for urls, because they don't really behave like - // standard function calls. The difference is that the argument doesn't have - // to be enclosed within a string, so it can't be parsed as an Expression. - // - url: function () { - var value; - - if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; - value = $(this.entities.quoted) || $(this.entities.variable) || - $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; - - expect(')'); - - return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) - ? value : new(tree.Anonymous)(value), imports.paths); - }, - - dataURI: function () { - var obj; - - if ($(/^data:/)) { - obj = {}; - obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; - obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; - obj.base64 = $(/^;\s*base64/) || ''; - obj.data = $(/^,\s*[^)]+/); - - if (obj.data) { return obj } - } - }, - - // - // A Variable entity, such as `@fink`, in - // - // width: @fink + 2px - // - // We use a different parser for variable definitions, - // see `parsers.variable`. - // - variable: function () { - var name, index = i; - - if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { - return new(tree.Variable)(name, index, env.filename); - } - }, - - // - // A Hexadecimal color - // - // #4F3C2F - // - // `rgb` and `hsl` colors are parsed through the `entities.call` parser. - // - color: function () { - var rgb; - - if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { - return new(tree.Color)(rgb[1]); - } - }, - - // - // A Dimension, that is, a number and a unit - // - // 0.5em 95% - // - dimension: function () { - var value, c = input.charCodeAt(i); - if ((c > 57 || c < 45) || c === 47) return; - - if (value = $(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn|dpi)?/)) { - return new(tree.Dimension)(value[1], value[2]); - } - }, - - // - // JavaScript code to be evaluated - // - // `window.location.href` - // - javascript: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '`') { return } - - e && $('~'); - - if (str = $(/^`([^`]*)`/)) { - return new(tree.JavaScript)(str[1], i, e); - } - } - }, - - // - // The variable part of a variable definition. Used in the `rule` parser - // - // @fink: - // - variable: function () { - var name; - - if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } - }, - - // - // A font size/line-height shorthand - // - // small/12px - // - // We need to peek first, or we'll match on keywords and dimensions - // - shorthand: function () { - var a, b; - - if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; - - if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { - return new(tree.Shorthand)(a, b); - } - }, - - // - // Mixins - // - mixin: { - // - // A Mixin call, with an optional argument list - // - // #mixins > .square(#fff); - // .rounded(4px, black); - // .button; - // - // The `while` loop is there because mixins can be - // namespaced, but we only support the child and descendant - // selector for now. - // - call: function () { - var elements = [], e, c, args = [], arg, index = i, s = input.charAt(i), name, value, important = false; - - if (s !== '.' && s !== '#') { return } - - while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { - elements.push(new(tree.Element)(c, e, i)); - c = $('>'); - } - if ($('(')) { - while (arg = $(this.expression)) { - value = arg; - name = null; - - // Variable - if (arg.value.length == 1) { - var val = arg.value[0]; - if (val instanceof tree.Variable) { - if ($(':')) { - if (value = $(this.expression)) { - name = val.name; - } else { - throw new(Error)("Expected value"); - } - } - } - } - - args.push({ name: name, value: value }); - - if (! $(',')) { break } - } - if (! $(')')) throw new(Error)("Expected )"); - } - - if ($(this.important)) { - important = true; - } - - if (elements.length > 0 && ($(';') || peek('}'))) { - return new(tree.mixin.Call)(elements, args, index, env.filename, important); - } - }, - - // - // A Mixin definition, with a list of parameters - // - // .rounded (@radius: 2px, @color) { - // ... - // } - // - // Until we have a finer grained state-machine, we have to - // do a look-ahead, to make sure we don't have a mixin call. - // See the `rule` function for more information. - // - // We start by matching `.rounded (`, and then proceed on to - // the argument list, which has optional default values. - // We store the parameters in `params`, with a `value` key, - // if there is a value, such as in the case of `@radius`. - // - // Once we've got our params list, and a closing `)`, we parse - // the `{...}` block. - // - definition: function () { - var name, params = [], match, ruleset, param, value, cond, variadic = false; - if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || - peek(/^[^{]*(;|})/)) return; - - save(); - - if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { - name = match[1]; - - do { - if (input.charAt(i) === '.' && $(/^\.{3}/)) { - variadic = true; - break; - } else if (param = $(this.entities.variable) || $(this.entities.literal) - || $(this.entities.keyword)) { - // Variable - if (param instanceof tree.Variable) { - if ($(':')) { - value = expect(this.expression, 'expected expression'); - params.push({ name: param.name, value: value }); - } else if ($(/^\.{3}/)) { - params.push({ name: param.name, variadic: true }); - variadic = true; - break; - } else { - params.push({ name: param.name }); - } - } else { - params.push({ value: param }); - } - } else { - break; - } - } while ($(',')) - - expect(')'); - - if ($(/^when/)) { // Guard - cond = expect(this.conditions, 'expected condition'); - } - - ruleset = $(this.block); - - if (ruleset) { - return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); - } else { - restore(); - } - } - } - }, - - // - // Entities are the smallest recognized token, - // and can be found inside a rule's value. - // - entity: function () { - return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || - $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || - $(this.comment); - }, - - // - // A Rule terminator. Note that we use `peek()` to check for '}', - // because the `block` rule will be expecting it, but we still need to make sure - // it's there, if ';' was ommitted. - // - end: function () { - return $(';') || peek('}'); - }, - - // - // IE's alpha function - // - // alpha(opacity=88) - // - alpha: function () { - var value; - - if (! $(/^\(opacity=/i)) return; - if (value = $(/^\d+/) || $(this.entities.variable)) { - expect(')'); - return new(tree.Alpha)(value); - } - }, - - // - // A Selector Element - // - // div - // + h1 - // #socks - // input[type="text"] - // - // Elements are the building blocks for Selectors, - // they are made out of a `Combinator` (see combinator rule), - // and an element name, such as a tag a class, or `*`. - // - element: function () { - var e, t, c, v; - - c = $(this.combinator); - e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || - $('*') || $(this.attribute) || $(/^\([^)@]+\)/); - - if (! e) { - $('(') && (v = $(this.entities.variable)) && $(')') && (e = new(tree.Paren)(v)); - } - - if (e) { return new(tree.Element)(c, e, i) } - - if (c.value && c.value.charAt(0) === '&') { - return new(tree.Element)(c, null, i); - } - }, - - // - // Combinators combine elements together, in a Selector. - // - // Because our parser isn't white-space sensitive, special care - // has to be taken, when parsing the descendant combinator, ` `, - // as it's an empty space. We have to check the previous character - // in the input, to see if it's a ` ` character. More info on how - // we deal with this in *combinator.js*. - // - combinator: function () { - var match, c = input.charAt(i); - - if (c === '>' || c === '+' || c === '~') { - i++; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(c); - } else if (c === '&') { - match = '&'; - i++; - if(input.charAt(i) === ' ') { - match = '& '; - } - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(match); - } else if (input.charAt(i - 1) === ' ') { - return new(tree.Combinator)(" "); - } else { - return new(tree.Combinator)(null); - } - }, - - // - // A CSS Selector - // - // .class > div + h1 - // li a:hover - // - // Selectors are made out of one or more Elements, see above. - // - selector: function () { - var sel, e, elements = [], c, match; - - if ($('(')) { - sel = $(this.entity); - expect(')'); - return new(tree.Selector)([new(tree.Element)('', sel, i)]); - } - - while (e = $(this.element)) { - c = input.charAt(i); - elements.push(e) - if (c === '{' || c === '}' || c === ';' || c === ',') { break } - } - - if (elements.length > 0) { return new(tree.Selector)(elements) } - }, - tag: function () { - return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); - }, - attribute: function () { - var attr = '', key, val, op; - - if (! $('[')) return; - - if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { - if ((op = $(/^[|~*$^]?=/)) && - (val = $(this.entities.quoted) || $(/^[\w-]+/))) { - attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); - } else { attr = key } - } - - if (! $(']')) return; - - if (attr) { return "[" + attr + "]" } - }, - - // - // The `block` rule is used by `ruleset` and `mixin.definition`. - // It's a wrapper around the `primary` rule, with added `{}`. - // - block: function () { - var content; - - if ($('{') && (content = $(this.primary)) && $('}')) { - return content; - } - }, - - // - // div, .class, body > p {...} - // - ruleset: function () { - var selectors = [], s, rules, match; - save(); - - while (s = $(this.selector)) { - selectors.push(s); - $(this.comment); - if (! $(',')) { break } - $(this.comment); - } - - if (selectors.length > 0 && (rules = $(this.block))) { - return new(tree.Ruleset)(selectors, rules, env.strictImports); - } else { - // Backtrack - furthest = i; - restore(); - } - }, - rule: function () { - var name, value, c = input.charAt(i), important, match; - save(); - - if (c === '.' || c === '#' || c === '&') { return } - - if (name = $(this.variable) || $(this.property)) { - if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { - i += match[0].length - 1; - value = new(tree.Anonymous)(match[1]); - } else if (name === "font") { - value = $(this.font); - } else { - value = $(this.value); - } - important = $(this.important); - - if (value && $(this.end)) { - return new(tree.Rule)(name, value, important, memo); - } else { - furthest = i; - restore(); - } - } - }, - - // - // An @import directive - // - // @import "lib"; - // - // Depending on our environemnt, importing is done differently: - // In the browser, it's an XHR request, in Node, it would be a - // file-system operation. The function used for importing is - // stored in `import`, which we pass to the Import constructor. - // - "import": function () { - var path, features, index = i; - var dir = $(/^@import(?:-(once))?\s+/); - - if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { - features = $(this.mediaFeatures); - if ($(';')) { - return new(tree.Import)(path, imports, features, (dir[1] === 'once'), index); - } - } - }, - - mediaFeature: function () { - var e, p, nodes = []; - - do { - if (e = $(this.entities.keyword)) { - nodes.push(e); - } else if ($('(')) { - p = $(this.property); - e = $(this.entity); - if ($(')')) { - if (p && e) { - nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); - } else if (e) { - nodes.push(new(tree.Paren)(e)); - } else { - return null; - } - } else { return null } - } - } while (e); - - if (nodes.length > 0) { - return new(tree.Expression)(nodes); - } - }, - - mediaFeatures: function () { - var e, features = []; - - do { - if (e = $(this.mediaFeature)) { - features.push(e); - if (! $(',')) { break } - } else if (e = $(this.entities.variable)) { - features.push(e); - if (! $(',')) { break } - } - } while (e); - - return features.length > 0 ? features : null; - }, - - media: function () { - var features, rules; - - if ($(/^@media/)) { - features = $(this.mediaFeatures); - - if (rules = $(this.block)) { - return new(tree.Media)(rules, features); - } - } - }, - - // - // A CSS Directive - // - // @charset "utf-8"; - // - directive: function () { - var name, value, rules, types, e, nodes; - - if (input.charAt(i) !== '@') return; - - if (value = $(this['import']) || $(this.media)) { - return value; - } else if (name = $(/^@page|@keyframes/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)) { - types = ($(/^[^{]+/) || '').trim(); - if (rules = $(this.block)) { - return new(tree.Directive)(name + " " + types, rules); - } - } else if (name = $(/^@[-a-z]+/)) { - if (name === '@font-face') { - if (rules = $(this.block)) { - return new(tree.Directive)(name, rules); - } - } else if ((value = $(this.entity)) && $(';')) { - return new(tree.Directive)(name, value); - } - } - }, - font: function () { - var value = [], expression = [], weight, shorthand, font, e; - - while (e = $(this.shorthand) || $(this.entity)) { - expression.push(e); - } - value.push(new(tree.Expression)(expression)); - - if ($(',')) { - while (e = $(this.expression)) { - value.push(e); - if (! $(',')) { break } - } - } - return new(tree.Value)(value); - }, - - // - // A Value is a comma-delimited list of Expressions - // - // font-family: Baskerville, Georgia, serif; - // - // In a Rule, a Value represents everything after the `:`, - // and before the `;`. - // - value: function () { - var e, expressions = [], important; - - while (e = $(this.expression)) { - expressions.push(e); - if (! $(',')) { break } - } - - if (expressions.length > 0) { - return new(tree.Value)(expressions); - } - }, - important: function () { - if (input.charAt(i) === '!') { - return $(/^! *important/); - } - }, - sub: function () { - var e; - - if ($('(') && (e = $(this.expression)) && $(')')) { - return e; - } - }, - multiplication: function () { - var m, a, op, operation; - if (m = $(this.operand)) { - while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - addition: function () { - var m, a, op, operation; - if (m = $(this.multiplication)) { - while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && - (a = $(this.multiplication))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - conditions: function () { - var a, b, index = i, condition; - - if (a = $(this.condition)) { - while ($(',') && (b = $(this.condition))) { - condition = new(tree.Condition)('or', condition || a, b, index); - } - return condition || a; - } - }, - condition: function () { - var a, b, c, op, index = i, negate = false; - - if ($(/^not/)) { negate = true } - expect('('); - if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { - if (op = $(/^(?:>=|=<|[<=>])/)) { - if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { - c = new(tree.Condition)(op, a, b, index, negate); - } else { - error('expected expression'); - } - } else { - c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); - } - expect(')'); - return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; - } - }, - - // - // An operand is anything that can be part of an operation, - // such as a Color, or a Variable - // - operand: function () { - var negate, p = input.charAt(i + 1); - - if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } - var o = $(this.sub) || $(this.entities.dimension) || - $(this.entities.color) || $(this.entities.variable) || - $(this.entities.call); - return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) - : o; - }, - - // - // Expressions either represent mathematical operations, - // or white-space delimited Entities. - // - // 1px solid black - // @var * 2 - // - expression: function () { - var e, delim, entities = [], d; - - while (e = $(this.addition) || $(this.entity)) { - entities.push(e); - } - if (entities.length > 0) { - return new(tree.Expression)(entities); - } - }, - property: function () { - var name; - - if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { - return name[1]; - } - } - } - }; -}; - -if (less.mode === 'browser' || less.mode === 'rhino') { - // - // Used by `@import` directives - // - less.Parser.importer = function (path, paths, callback, env) { - if (!/^([a-z]+:)?\//.test(path) && paths.length > 0) { - path = paths[0] + path; - } - // We pass `true` as 3rd argument, to force the reload of the import. - // This is so we can get the syntax tree as opposed to just the CSS output, - // as we need this to evaluate the current stylesheet. - loadStyleSheet({ href: path, title: path, type: env.mime }, function (e) { - if (e && typeof(env.errback) === "function") { - env.errback.call(null, path, paths, callback, env); - } else { - callback.apply(null, arguments); - } - }, true); - }; -} - diff --git a/dashboard/bin/lib/less/rhino.js b/dashboard/bin/lib/less/rhino.js deleted file mode 100644 index a2c5662f..00000000 --- a/dashboard/bin/lib/less/rhino.js +++ /dev/null @@ -1,62 +0,0 @@ -var name; - -function loadStyleSheet(sheet, callback, reload, remaining) { - var sheetName = name.slice(0, name.lastIndexOf('/') + 1) + sheet.href; - var input = readFile(sheetName); - var parser = new less.Parser({ - paths: [sheet.href.replace(/[\w\.-]+$/, '')] - }); - parser.parse(input, function (e, root) { - if (e) { - print("Error: " + e); - quit(1); - } - callback(root, sheet, { local: false, lastModified: 0, remaining: remaining }); - }); - - // callback({}, sheet, { local: true, remaining: remaining }); -} - -function writeFile(filename, content) { - var fstream = new java.io.FileWriter(filename); - var out = new java.io.BufferedWriter(fstream); - out.write(content); - out.close(); -} - -// Command line integration via Rhino -(function (args) { - name = args[0]; - var output = args[1]; - - if (!name) { - print('No files present in the fileset; Check your pattern match in build.xml'); - quit(1); - } - path = name.split("/");path.pop();path=path.join("/") - - var input = readFile(name); - - if (!input) { - print('lesscss: couldn\'t open file ' + name); - quit(1); - } - - var result; - var parser = new less.Parser(); - parser.parse(input, function (e, root) { - if (e) { - quit(1); - } else { - result = root.toCSS(); - if (output) { - writeFile(output, result); - print("Written to " + output); - } else { - print(result); - } - quit(0); - } - }); - print("done"); -}(arguments)); diff --git a/dashboard/bin/lib/less/tree.js b/dashboard/bin/lib/less/tree.js deleted file mode 100644 index 24ecd712..00000000 --- a/dashboard/bin/lib/less/tree.js +++ /dev/null @@ -1,17 +0,0 @@ -(function (tree) { - -tree.find = function (obj, fun) { - for (var i = 0, r; i < obj.length; i++) { - if (r = fun.call(obj, obj[i])) { return r } - } - return null; -}; -tree.jsify = function (obj) { - if (Array.isArray(obj.value) && (obj.value.length > 1)) { - return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; - } else { - return obj.toCSS(false); - } -}; - -})(require('./tree')); diff --git a/dashboard/bin/lib/less/tree/alpha.js b/dashboard/bin/lib/less/tree/alpha.js deleted file mode 100644 index 139ae920..00000000 --- a/dashboard/bin/lib/less/tree/alpha.js +++ /dev/null @@ -1,17 +0,0 @@ -(function (tree) { - -tree.Alpha = function (val) { - this.value = val; -}; -tree.Alpha.prototype = { - toCSS: function () { - return "alpha(opacity=" + - (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } -}; - -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/anonymous.js b/dashboard/bin/lib/less/tree/anonymous.js deleted file mode 100644 index 460c9ec7..00000000 --- a/dashboard/bin/lib/less/tree/anonymous.js +++ /dev/null @@ -1,13 +0,0 @@ -(function (tree) { - -tree.Anonymous = function (string) { - this.value = string.value || string; -}; -tree.Anonymous.prototype = { - toCSS: function () { - return this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/assignment.js b/dashboard/bin/lib/less/tree/assignment.js deleted file mode 100644 index 70ce6e2f..00000000 --- a/dashboard/bin/lib/less/tree/assignment.js +++ /dev/null @@ -1,17 +0,0 @@ -(function (tree) { - -tree.Assignment = function (key, val) { - this.key = key; - this.value = val; -}; -tree.Assignment.prototype = { - toCSS: function () { - return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } -}; - -})(require('../tree')); \ No newline at end of file diff --git a/dashboard/bin/lib/less/tree/call.js b/dashboard/bin/lib/less/tree/call.js deleted file mode 100644 index c1465dd4..00000000 --- a/dashboard/bin/lib/less/tree/call.js +++ /dev/null @@ -1,48 +0,0 @@ -(function (tree) { - -// -// A function call node. -// -tree.Call = function (name, args, index, filename) { - this.name = name; - this.args = args; - this.index = index; - this.filename = filename; -}; -tree.Call.prototype = { - // - // When evaluating a function call, - // we either find the function in `tree.functions` [1], - // in which case we call it, passing the evaluated arguments, - // or we simply print it out as it appeared originally [2]. - // - // The *functions.js* file contains the built-in functions. - // - // The reason why we evaluate the arguments, is in the case where - // we try to pass a variable to a function, like: `saturate(@color)`. - // The function should receive the value, not the variable. - // - eval: function (env) { - var args = this.args.map(function (a) { return a.eval(env) }); - - if (this.name in tree.functions) { // 1. - try { - return tree.functions[this.name].apply(tree.functions, args); - } catch (e) { - throw { type: e.type || "Runtime", - message: "error evaluating function `" + this.name + "`" + - (e.message ? ': ' + e.message : ''), - index: this.index, filename: this.filename }; - } - } else { // 2. - return new(tree.Anonymous)(this.name + - "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); - } - }, - - toCSS: function (env) { - return this.eval(env).toCSS(); - } -}; - -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/color.js b/dashboard/bin/lib/less/tree/color.js deleted file mode 100644 index 37ce1781..00000000 --- a/dashboard/bin/lib/less/tree/color.js +++ /dev/null @@ -1,101 +0,0 @@ -(function (tree) { -// -// RGB Colors - #ff0014, #eee -// -tree.Color = function (rgb, a) { - // - // The end goal here, is to parse the arguments - // into an integer triplet, such as `128, 255, 0` - // - // This facilitates operations and conversions. - // - if (Array.isArray(rgb)) { - this.rgb = rgb; - } else if (rgb.length == 6) { - this.rgb = rgb.match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else { - this.rgb = rgb.split('').map(function (c) { - return parseInt(c + c, 16); - }); - } - this.alpha = typeof(a) === 'number' ? a : 1; -}; -tree.Color.prototype = { - eval: function () { return this }, - - // - // If we have some transparency, the only way to represent it - // is via `rgba`. Otherwise, we use the hex representation, - // which has better compatibility with older browsers. - // Values are capped between `0` and `255`, rounded and zero-padded. - // - toCSS: function () { - if (this.alpha < 1.0) { - return "rgba(" + this.rgb.map(function (c) { - return Math.round(c); - }).concat(this.alpha).join(', ') + ")"; - } else { - return '#' + this.rgb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } - }, - - // - // Operations have to be done per-channel, if not, - // channels will spill onto each other. Once we have - // our result, in the form of an integer triplet, - // we create a new Color node to hold the result. - // - operate: function (op, other) { - var result = []; - - if (! (other instanceof tree.Color)) { - other = other.toColor(); - } - - for (var c = 0; c < 3; c++) { - result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); - } - return new(tree.Color)(result, this.alpha + other.alpha); - }, - - toHSL: function () { - var r = this.rgb[0] / 255, - g = this.rgb[1] / 255, - b = this.rgb[2] / 255, - a = this.alpha; - - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, l = (max + min) / 2, d = max - min; - - if (max === min) { - h = s = 0; - } else { - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - return { h: h * 360, s: s, l: l, a: a }; - }, - toARGB: function () { - var argb = [Math.round(this.alpha * 255)].concat(this.rgb); - return '#' + argb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } -}; - - -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/comment.js b/dashboard/bin/lib/less/tree/comment.js deleted file mode 100644 index f4a33840..00000000 --- a/dashboard/bin/lib/less/tree/comment.js +++ /dev/null @@ -1,14 +0,0 @@ -(function (tree) { - -tree.Comment = function (value, silent) { - this.value = value; - this.silent = !!silent; -}; -tree.Comment.prototype = { - toCSS: function (env) { - return env.compress ? '' : this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/condition.js b/dashboard/bin/lib/less/tree/condition.js deleted file mode 100644 index 6b79dc96..00000000 --- a/dashboard/bin/lib/less/tree/condition.js +++ /dev/null @@ -1,42 +0,0 @@ -(function (tree) { - -tree.Condition = function (op, l, r, i, negate) { - this.op = op.trim(); - this.lvalue = l; - this.rvalue = r; - this.index = i; - this.negate = negate; -}; -tree.Condition.prototype.eval = function (env) { - var a = this.lvalue.eval(env), - b = this.rvalue.eval(env); - - var i = this.index, result; - - var result = (function (op) { - switch (op) { - case 'and': - return a && b; - case 'or': - return a || b; - default: - if (a.compare) { - result = a.compare(b); - } else if (b.compare) { - result = b.compare(a); - } else { - throw { type: "Type", - message: "Unable to perform comparison", - index: i }; - } - switch (result) { - case -1: return op === '<' || op === '=<'; - case 0: return op === '=' || op === '>=' || op === '=<'; - case 1: return op === '>' || op === '>='; - } - } - })(this.op); - return this.negate ? !result : result; -}; - -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/dimension.js b/dashboard/bin/lib/less/tree/dimension.js deleted file mode 100644 index 9a6fce3d..00000000 --- a/dashboard/bin/lib/less/tree/dimension.js +++ /dev/null @@ -1,49 +0,0 @@ -(function (tree) { - -// -// A number with a unit -// -tree.Dimension = function (value, unit) { - this.value = parseFloat(value); - this.unit = unit || null; -}; - -tree.Dimension.prototype = { - eval: function () { return this }, - toColor: function () { - return new(tree.Color)([this.value, this.value, this.value]); - }, - toCSS: function () { - var css = this.value + this.unit; - return css; - }, - - // In an operation between two Dimensions, - // we default to the first Dimension's unit, - // so `1px + 2em` will yield `3px`. - // In the future, we could implement some unit - // conversions such that `100cm + 10mm` would yield - // `101cm`. - operate: function (op, other) { - return new(tree.Dimension) - (tree.operate(op, this.value, other.value), - this.unit || other.unit); - }, - - // TODO: Perform unit conversion before comparing - compare: function (other) { - if (other instanceof tree.Dimension) { - if (other.value > this.value) { - return -1; - } else if (other.value < this.value) { - return 1; - } else { - return 0; - } - } else { - return -1; - } - } -}; - -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/directive.js b/dashboard/bin/lib/less/tree/directive.js deleted file mode 100644 index 27538332..00000000 --- a/dashboard/bin/lib/less/tree/directive.js +++ /dev/null @@ -1,35 +0,0 @@ -(function (tree) { - -tree.Directive = function (name, value, features) { - this.name = name; - - if (Array.isArray(value)) { - this.ruleset = new(tree.Ruleset)([], value); - this.ruleset.allowImports = true; - } else { - this.value = value; - } -}; -tree.Directive.prototype = { - toCSS: function (ctx, env) { - if (this.ruleset) { - this.ruleset.root = true; - return this.name + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - } else { - return this.name + ' ' + this.value.toCSS() + ';\n'; - } - }, - eval: function (env) { - env.frames.unshift(this); - this.ruleset = this.ruleset && this.ruleset.eval(env); - env.frames.shift(); - return this; - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } -}; - -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/element.js b/dashboard/bin/lib/less/tree/element.js deleted file mode 100644 index 14b08d2e..00000000 --- a/dashboard/bin/lib/less/tree/element.js +++ /dev/null @@ -1,52 +0,0 @@ -(function (tree) { - -tree.Element = function (combinator, value, index) { - this.combinator = combinator instanceof tree.Combinator ? - combinator : new(tree.Combinator)(combinator); - - if (typeof(value) === 'string') { - this.value = value.trim(); - } else if (value) { - this.value = value; - } else { - this.value = ""; - } - this.index = index; -}; -tree.Element.prototype.eval = function (env) { - return new(tree.Element)(this.combinator, - this.value.eval ? this.value.eval(env) : this.value, - this.index); -}; -tree.Element.prototype.toCSS = function (env) { - var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); - if (value == '' && this.combinator.value.charAt(0) == '&') { - return ''; - } else { - return this.combinator.toCSS(env || {}) + value; - } -}; - -tree.Combinator = function (value) { - if (value === ' ') { - this.value = ' '; - } else if (value === '& ') { - this.value = '& '; - } else { - this.value = value ? value.trim() : ""; - } -}; -tree.Combinator.prototype.toCSS = function (env) { - return { - '' : '', - ' ' : ' ', - '&' : '', - '& ' : ' ', - ':' : ' :', - '+' : env.compress ? '+' : ' + ', - '~' : env.compress ? '~' : ' ~ ', - '>' : env.compress ? '>' : ' > ' - }[this.value]; -}; - -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/expression.js b/dashboard/bin/lib/less/tree/expression.js deleted file mode 100644 index fbfa9c5b..00000000 --- a/dashboard/bin/lib/less/tree/expression.js +++ /dev/null @@ -1,23 +0,0 @@ -(function (tree) { - -tree.Expression = function (value) { this.value = value }; -tree.Expression.prototype = { - eval: function (env) { - if (this.value.length > 1) { - return new(tree.Expression)(this.value.map(function (e) { - return e.eval(env); - })); - } else if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return this; - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS ? e.toCSS(env) : ''; - }).join(' '); - } -}; - -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/import.js b/dashboard/bin/lib/less/tree/import.js deleted file mode 100644 index 7a977def..00000000 --- a/dashboard/bin/lib/less/tree/import.js +++ /dev/null @@ -1,83 +0,0 @@ -(function (tree) { -// -// CSS @import node -// -// The general strategy here is that we don't want to wait -// for the parsing to be completed, before we start importing -// the file. That's because in the context of a browser, -// most of the time will be spent waiting for the server to respond. -// -// On creation, we push the import path to our import queue, though -// `import,push`, we also pass it a callback, which it'll call once -// the file has been fetched, and parsed. -// -tree.Import = function (path, imports, features, once, index) { - var that = this; - - this.once = once; - this.index = index; - this._path = path; - this.features = features && new(tree.Value)(features); - - // The '.less' extension is optional - if (path instanceof tree.Quoted) { - this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; - } else { - this.path = path.value.value || path.value; - } - - this.css = /css(\?.*)?$/.test(this.path); - - // Only pre-compile .less files - if (! this.css) { - imports.push(this.path, function (e, root, imported) { - if (e) { e.index = index } - if (imported && that.once) that.skip = imported; - that.root = root || new(tree.Ruleset)([], []); - }); - } -}; - -// -// The actual import node doesn't return anything, when converted to CSS. -// The reason is that it's used at the evaluation stage, so that the rules -// it imports can be treated like any other rules. -// -// In `eval`, we make sure all Import nodes get evaluated, recursively, so -// we end up with a flat structure, which can easily be imported in the parent -// ruleset. -// -tree.Import.prototype = { - toCSS: function (env) { - var features = this.features ? ' ' + this.features.toCSS(env) : ''; - - if (this.css) { - return "@import " + this._path.toCSS() + features + ';\n'; - } else { - return ""; - } - }, - eval: function (env) { - var ruleset, features = this.features && this.features.eval(env); - - if (this.skip) return []; - - if (this.css) { - return this; - } else { - ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); - - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype - .splice - .apply(ruleset.rules, - [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; - } - } -}; - -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/javascript.js b/dashboard/bin/lib/less/tree/javascript.js deleted file mode 100644 index 772a31dd..00000000 --- a/dashboard/bin/lib/less/tree/javascript.js +++ /dev/null @@ -1,51 +0,0 @@ -(function (tree) { - -tree.JavaScript = function (string, index, escaped) { - this.escaped = escaped; - this.expression = string; - this.index = index; -}; -tree.JavaScript.prototype = { - eval: function (env) { - var result, - that = this, - context = {}; - - var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { - return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); - }); - - try { - expression = new(Function)('return (' + expression + ')'); - } catch (e) { - throw { message: "JavaScript evaluation error: `" + expression + "`" , - index: this.index }; - } - - for (var k in env.frames[0].variables()) { - context[k.slice(1)] = { - value: env.frames[0].variables()[k].value, - toJS: function () { - return this.value.eval(env).toCSS(); - } - }; - } - - try { - result = expression.call(context); - } catch (e) { - throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , - index: this.index }; - } - if (typeof(result) === 'string') { - return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); - } else if (Array.isArray(result)) { - return new(tree.Anonymous)(result.join(', ')); - } else { - return new(tree.Anonymous)(result); - } - } -}; - -})(require('../tree')); - diff --git a/dashboard/bin/lib/less/tree/keyword.js b/dashboard/bin/lib/less/tree/keyword.js deleted file mode 100644 index 701b79e5..00000000 --- a/dashboard/bin/lib/less/tree/keyword.js +++ /dev/null @@ -1,19 +0,0 @@ -(function (tree) { - -tree.Keyword = function (value) { this.value = value }; -tree.Keyword.prototype = { - eval: function () { return this }, - toCSS: function () { return this.value }, - compare: function (other) { - if (other instanceof tree.Keyword) { - return other.value === this.value ? 0 : 1; - } else { - return -1; - } - } -}; - -tree.True = new(tree.Keyword)('true'); -tree.False = new(tree.Keyword)('false'); - -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/media.js b/dashboard/bin/lib/less/tree/media.js deleted file mode 100644 index 2b7b26e5..00000000 --- a/dashboard/bin/lib/less/tree/media.js +++ /dev/null @@ -1,114 +0,0 @@ -(function (tree) { - -tree.Media = function (value, features) { - var el = new(tree.Element)('&', null, 0), - selectors = [new(tree.Selector)([el])]; - - this.features = new(tree.Value)(features); - this.ruleset = new(tree.Ruleset)(selectors, value); - this.ruleset.allowImports = true; -}; -tree.Media.prototype = { - toCSS: function (ctx, env) { - var features = this.features.toCSS(env); - - this.ruleset.root = (ctx.length === 0 || ctx[0].multiMedia); - return '@media ' + features + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - }, - eval: function (env) { - if (!env.mediaBlocks) { - env.mediaBlocks = []; - env.mediaPath = []; - } - - var blockIndex = env.mediaBlocks.length; - env.mediaPath.push(this); - env.mediaBlocks.push(this); - - var media = new(tree.Media)([], []); - media.features = this.features.eval(env); - - env.frames.unshift(this.ruleset); - media.ruleset = this.ruleset.eval(env); - env.frames.shift(); - - env.mediaBlocks[blockIndex] = media; - env.mediaPath.pop(); - - return env.mediaPath.length === 0 ? media.evalTop(env) : - media.evalNested(env) - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, - - evalTop: function (env) { - var result = this; - - // Render all dependent Media blocks. - if (env.mediaBlocks.length > 1) { - var el = new(tree.Element)('&', null, 0); - var selectors = [new(tree.Selector)([el])]; - result = new(tree.Ruleset)(selectors, env.mediaBlocks); - result.multiMedia = true; - } - - delete env.mediaBlocks; - delete env.mediaPath; - - return result; - }, - evalNested: function (env) { - var i, value, - path = env.mediaPath.concat([this]); - - // Extract the media-query conditions separated with `,` (OR). - for (i = 0; i < path.length; i++) { - value = path[i].features instanceof tree.Value ? - path[i].features.value : path[i].features; - path[i] = Array.isArray(value) ? value : [value]; - } - - // Trace all permutations to generate the resulting media-query. - // - // (a, b and c) with nested (d, e) -> - // a and d - // a and e - // b and c and d - // b and c and e - this.features = new(tree.Value)(this.permute(path).map(function (path) { - path = path.map(function (fragment) { - return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); - }); - - for(i = path.length - 1; i > 0; i--) { - path.splice(i, 0, new(tree.Anonymous)("and")); - } - - return new(tree.Expression)(path); - })); - - // Fake a tree-node that doesn't output anything. - return new(tree.Ruleset)([], []); - }, - permute: function (arr) { - if (arr.length === 0) { - return []; - } else if (arr.length === 1) { - return arr[0]; - } else { - var result = []; - var rest = this.permute(arr.slice(1)); - for (var i = 0; i < rest.length; i++) { - for (var j = 0; j < arr[0].length; j++) { - result.push([arr[0][j]].concat(rest[i])); - } - } - return result; - } - } -}; - -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/mixin.js b/dashboard/bin/lib/less/tree/mixin.js deleted file mode 100644 index b441bf3b..00000000 --- a/dashboard/bin/lib/less/tree/mixin.js +++ /dev/null @@ -1,146 +0,0 @@ -(function (tree) { - -tree.mixin = {}; -tree.mixin.Call = function (elements, args, index, filename, important) { - this.selector = new(tree.Selector)(elements); - this.arguments = args; - this.index = index; - this.filename = filename; - this.important = important; -}; -tree.mixin.Call.prototype = { - eval: function (env) { - var mixins, args, rules = [], match = false; - - for (var i = 0; i < env.frames.length; i++) { - if ((mixins = env.frames[i].find(this.selector)).length > 0) { - args = this.arguments && this.arguments.map(function (a) { - return { name: a.name, value: a.value.eval(env) }; - }); - for (var m = 0; m < mixins.length; m++) { - if (mixins[m].match(args, env)) { - try { - Array.prototype.push.apply( - rules, mixins[m].eval(env, this.arguments, this.important).rules); - match = true; - } catch (e) { - throw { message: e.message, index: this.index, filename: this.filename, stack: e.stack }; - } - } - } - if (match) { - return rules; - } else { - throw { type: 'Runtime', - message: 'No matching definition was found for `' + - this.selector.toCSS().trim() + '(' + - this.arguments.map(function (a) { - return a.toCSS(); - }).join(', ') + ")`", - index: this.index, filename: this.filename }; - } - } - } - throw { type: 'Name', - message: this.selector.toCSS().trim() + " is undefined", - index: this.index, filename: this.filename }; - } -}; - -tree.mixin.Definition = function (name, params, rules, condition, variadic) { - this.name = name; - this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; - this.params = params; - this.condition = condition; - this.variadic = variadic; - this.arity = params.length; - this.rules = rules; - this._lookups = {}; - this.required = params.reduce(function (count, p) { - if (!p.name || (p.name && !p.value)) { return count + 1 } - else { return count } - }, 0); - this.parent = tree.Ruleset.prototype; - this.frames = []; -}; -tree.mixin.Definition.prototype = { - toCSS: function () { return "" }, - variable: function (name) { return this.parent.variable.call(this, name) }, - variables: function () { return this.parent.variables.call(this) }, - find: function () { return this.parent.find.apply(this, arguments) }, - rulesets: function () { return this.parent.rulesets.apply(this) }, - - evalParams: function (env, args) { - var frame = new(tree.Ruleset)(null, []), varargs, arg; - - for (var i = 0, val, name; i < this.params.length; i++) { - arg = args && args[i] - - if (arg && arg.name) { - frame.rules.unshift(new(tree.Rule)(arg.name, arg.value.eval(env))); - args.splice(i, 1); - i--; - continue; - } - - if (name = this.params[i].name) { - if (this.params[i].variadic && args) { - varargs = []; - for (var j = i; j < args.length; j++) { - varargs.push(args[j].value.eval(env)); - } - frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); - } else if (val = (arg && arg.value) || this.params[i].value) { - frame.rules.unshift(new(tree.Rule)(name, val.eval(env))); - } else { - throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + - ' (' + args.length + ' for ' + this.arity + ')' }; - } - } - } - return frame; - }, - eval: function (env, args, important) { - var frame = this.evalParams(env, args), context, _arguments = [], rules, start; - - for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { - _arguments.push((args[i] && args[i].value) || this.params[i].value); - } - frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); - - rules = important ? - this.rules.map(function (r) { - return new(tree.Rule)(r.name, r.value, '!important', r.index); - }) : this.rules.slice(0); - - return new(tree.Ruleset)(null, rules).eval({ - frames: [this, frame].concat(this.frames, env.frames) - }); - }, - match: function (args, env) { - var argsLength = (args && args.length) || 0, len, frame; - - if (! this.variadic) { - if (argsLength < this.required) { return false } - if (argsLength > this.params.length) { return false } - if ((this.required > 0) && (argsLength > this.params.length)) { return false } - } - - if (this.condition && !this.condition.eval({ - frames: [this.evalParams(env, args)].concat(env.frames) - })) { return false } - - len = Math.min(argsLength, this.arity); - - for (var i = 0; i < len; i++) { - if (!this.params[i].name) { - if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { - return false; - } - } - } - return true; - } -}; - -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/operation.js b/dashboard/bin/lib/less/tree/operation.js deleted file mode 100644 index 1ce22fb0..00000000 --- a/dashboard/bin/lib/less/tree/operation.js +++ /dev/null @@ -1,32 +0,0 @@ -(function (tree) { - -tree.Operation = function (op, operands) { - this.op = op.trim(); - this.operands = operands; -}; -tree.Operation.prototype.eval = function (env) { - var a = this.operands[0].eval(env), - b = this.operands[1].eval(env), - temp; - - if (a instanceof tree.Dimension && b instanceof tree.Color) { - if (this.op === '*' || this.op === '+') { - temp = b, b = a, a = temp; - } else { - throw { name: "OperationError", - message: "Can't substract or divide a color from a number" }; - } - } - return a.operate(this.op, b); -}; - -tree.operate = function (op, a, b) { - switch (op) { - case '+': return a + b; - case '-': return a - b; - case '*': return a * b; - case '/': return a / b; - } -}; - -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/paren.js b/dashboard/bin/lib/less/tree/paren.js deleted file mode 100644 index 384a43c7..00000000 --- a/dashboard/bin/lib/less/tree/paren.js +++ /dev/null @@ -1,16 +0,0 @@ - -(function (tree) { - -tree.Paren = function (node) { - this.value = node; -}; -tree.Paren.prototype = { - toCSS: function (env) { - return '(' + this.value.toCSS(env) + ')'; - }, - eval: function (env) { - return new(tree.Paren)(this.value.eval(env)); - } -}; - -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/quoted.js b/dashboard/bin/lib/less/tree/quoted.js deleted file mode 100644 index 794bf4ce..00000000 --- a/dashboard/bin/lib/less/tree/quoted.js +++ /dev/null @@ -1,29 +0,0 @@ -(function (tree) { - -tree.Quoted = function (str, content, escaped, i) { - this.escaped = escaped; - this.value = content || ''; - this.quote = str.charAt(0); - this.index = i; -}; -tree.Quoted.prototype = { - toCSS: function () { - if (this.escaped) { - return this.value; - } else { - return this.quote + this.value + this.quote; - } - }, - eval: function (env) { - var that = this; - var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { - return new(tree.JavaScript)(exp, that.index, true).eval(env).value; - }).replace(/@\{([\w-]+)\}/g, function (_, name) { - var v = new(tree.Variable)('@' + name, that.index).eval(env); - return ('value' in v) ? v.value : v.toCSS(); - }); - return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); - } -}; - -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/rule.js b/dashboard/bin/lib/less/tree/rule.js deleted file mode 100644 index 9e4e54a3..00000000 --- a/dashboard/bin/lib/less/tree/rule.js +++ /dev/null @@ -1,42 +0,0 @@ -(function (tree) { - -tree.Rule = function (name, value, important, index, inline) { - this.name = name; - this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); - this.important = important ? ' ' + important.trim() : ''; - this.index = index; - this.inline = inline || false; - - if (name.charAt(0) === '@') { - this.variable = true; - } else { this.variable = false } -}; -tree.Rule.prototype.toCSS = function (env) { - if (this.variable) { return "" } - else { - return this.name + (env.compress ? ':' : ': ') + - this.value.toCSS(env) + - this.important + (this.inline ? "" : ";"); - } -}; - -tree.Rule.prototype.eval = function (context) { - return new(tree.Rule)(this.name, - this.value.eval(context), - this.important, - this.index, this.inline); -}; - -tree.Shorthand = function (a, b) { - this.a = a; - this.b = b; -}; - -tree.Shorthand.prototype = { - toCSS: function (env) { - return this.a.toCSS(env) + "/" + this.b.toCSS(env); - }, - eval: function () { return this } -}; - -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/ruleset.js b/dashboard/bin/lib/less/tree/ruleset.js deleted file mode 100644 index 3100cc35..00000000 --- a/dashboard/bin/lib/less/tree/ruleset.js +++ /dev/null @@ -1,225 +0,0 @@ -(function (tree) { - -tree.Ruleset = function (selectors, rules, strictImports) { - this.selectors = selectors; - this.rules = rules; - this._lookups = {}; - this.strictImports = strictImports; -}; -tree.Ruleset.prototype = { - eval: function (env) { - var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); - var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); - - ruleset.root = this.root; - ruleset.allowImports = this.allowImports; - - // push the current ruleset to the frames stack - env.frames.unshift(ruleset); - - // Evaluate imports - if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - } - - // Store the frames around mixin definitions, - // so they can be evaluated like closures when the time comes. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Definition) { - ruleset.rules[i].frames = env.frames.slice(0); - } - } - - // Evaluate mixin calls. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Call) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - - // Evaluate everything else - for (var i = 0, rule; i < ruleset.rules.length; i++) { - rule = ruleset.rules[i]; - - if (! (rule instanceof tree.mixin.Definition)) { - ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; - } - } - - // Pop the stack - env.frames.shift(); - - return ruleset; - }, - match: function (args) { - return !args || args.length === 0; - }, - variables: function () { - if (this._variables) { return this._variables } - else { - return this._variables = this.rules.reduce(function (hash, r) { - if (r instanceof tree.Rule && r.variable === true) { - hash[r.name] = r; - } - return hash; - }, {}); - } - }, - variable: function (name) { - return this.variables()[name]; - }, - rulesets: function () { - if (this._rulesets) { return this._rulesets } - else { - return this._rulesets = this.rules.filter(function (r) { - return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); - }); - } - }, - find: function (selector, self) { - self = self || this; - var rules = [], rule, match, - key = selector.toCSS(); - - if (key in this._lookups) { return this._lookups[key] } - - this.rulesets().forEach(function (rule) { - if (rule !== self) { - for (var j = 0; j < rule.selectors.length; j++) { - if (match = selector.match(rule.selectors[j])) { - if (selector.elements.length > rule.selectors[j].elements.length) { - Array.prototype.push.apply(rules, rule.find( - new(tree.Selector)(selector.elements.slice(1)), self)); - } else { - rules.push(rule); - } - break; - } - } - } - }); - return this._lookups[key] = rules; - }, - // - // Entry point for code generation - // - // `context` holds an array of arrays. - // - toCSS: function (context, env) { - var css = [], // The CSS output - rules = [], // node.Rule instances - _rules = [], // - rulesets = [], // node.Ruleset instances - paths = [], // Current selectors - selector, // The fully rendered selector - rule; - - if (! this.root) { - if (context.length === 0) { - paths = this.selectors.map(function (s) { return [s] }); - } else { - this.joinSelectors(paths, context, this.selectors); - } - } - - // Compile rules and rulesets - for (var i = 0; i < this.rules.length; i++) { - rule = this.rules[i]; - - if (rule.rules || (rule instanceof tree.Directive) || (rule instanceof tree.Media)) { - rulesets.push(rule.toCSS(paths, env)); - } else if (rule instanceof tree.Comment) { - if (!rule.silent) { - if (this.root) { - rulesets.push(rule.toCSS(env)); - } else { - rules.push(rule.toCSS(env)); - } - } - } else { - if (rule.toCSS && !rule.variable) { - rules.push(rule.toCSS(env)); - } else if (rule.value && !rule.variable) { - rules.push(rule.value.toString()); - } - } - } - - rulesets = rulesets.join(''); - - // If this is the root node, we don't render - // a selector, or {}. - // Otherwise, only output if this ruleset has rules. - if (this.root) { - css.push(rules.join(env.compress ? '' : '\n')); - } else { - if (rules.length > 0) { - selector = paths.map(function (p) { - return p.map(function (s) { - return s.toCSS(env); - }).join('').trim(); - }).join(env.compress ? ',' : ',\n'); - - // Remove duplicates - for (var i = rules.length - 1; i >= 0; i--) { - if (_rules.indexOf(rules[i]) === -1) { - _rules.unshift(rules[i]); - } - } - rules = _rules; - - css.push(selector, - (env.compress ? '{' : ' {\n ') + - rules.join(env.compress ? '' : '\n ') + - (env.compress ? '}' : '\n}\n')); - } - } - css.push(rulesets); - - return css.join('') + (env.compress ? '\n' : ''); - }, - - joinSelectors: function (paths, context, selectors) { - for (var s = 0; s < selectors.length; s++) { - this.joinSelector(paths, context, selectors[s]); - } - }, - - joinSelector: function (paths, context, selector) { - var before = [], after = [], beforeElements = [], - afterElements = [], hasParentSelector = false, el; - - for (var i = 0; i < selector.elements.length; i++) { - el = selector.elements[i]; - if (el.combinator.value.charAt(0) === '&') { - hasParentSelector = true; - } - if (hasParentSelector) afterElements.push(el); - else beforeElements.push(el); - } - - if (! hasParentSelector) { - afterElements = beforeElements; - beforeElements = []; - } - - if (beforeElements.length > 0) { - before.push(new(tree.Selector)(beforeElements)); - } - - if (afterElements.length > 0) { - after.push(new(tree.Selector)(afterElements)); - } - - for (var c = 0; c < context.length; c++) { - paths.push(before.concat(context[c]).concat(after)); - } - } -}; -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/selector.js b/dashboard/bin/lib/less/tree/selector.js deleted file mode 100644 index 65abbb69..00000000 --- a/dashboard/bin/lib/less/tree/selector.js +++ /dev/null @@ -1,42 +0,0 @@ -(function (tree) { - -tree.Selector = function (elements) { - this.elements = elements; - if (this.elements[0].combinator.value === "") { - this.elements[0].combinator.value = ' '; - } -}; -tree.Selector.prototype.match = function (other) { - var len = this.elements.length, - olen = other.elements.length, - max = Math.min(len, olen); - - if (len < olen) { - return false; - } else { - for (var i = 0; i < max; i++) { - if (this.elements[i].value !== other.elements[i].value) { - return false; - } - } - } - return true; -}; -tree.Selector.prototype.eval = function (env) { - return new(tree.Selector)(this.elements.map(function (e) { - return e.eval(env); - })); -}; -tree.Selector.prototype.toCSS = function (env) { - if (this._css) { return this._css } - - return this._css = this.elements.map(function (e) { - if (typeof(e) === 'string') { - return ' ' + e.trim(); - } else { - return e.toCSS(env); - } - }).join(''); -}; - -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/url.js b/dashboard/bin/lib/less/tree/url.js deleted file mode 100644 index 0caec345..00000000 --- a/dashboard/bin/lib/less/tree/url.js +++ /dev/null @@ -1,25 +0,0 @@ -(function (tree) { - -tree.URL = function (val, paths) { - if (val.data) { - this.attrs = val; - } else { - // Add the base path if the URL is relative and we are in the browser - if (typeof(window) !== 'undefined' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { - val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); - } - this.value = val; - this.paths = paths; - } -}; -tree.URL.prototype = { - toCSS: function () { - return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data - : this.value.toCSS()) + ")"; - }, - eval: function (ctx) { - return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); - } -}; - -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/value.js b/dashboard/bin/lib/less/tree/value.js deleted file mode 100644 index 3c1eb29a..00000000 --- a/dashboard/bin/lib/less/tree/value.js +++ /dev/null @@ -1,24 +0,0 @@ -(function (tree) { - -tree.Value = function (value) { - this.value = value; - this.is = 'value'; -}; -tree.Value.prototype = { - eval: function (env) { - if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return new(tree.Value)(this.value.map(function (v) { - return v.eval(env); - })); - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(env.compress ? ',' : ', '); - } -}; - -})(require('../tree')); diff --git a/dashboard/bin/lib/less/tree/variable.js b/dashboard/bin/lib/less/tree/variable.js deleted file mode 100644 index ee557e1d..00000000 --- a/dashboard/bin/lib/less/tree/variable.js +++ /dev/null @@ -1,26 +0,0 @@ -(function (tree) { - -tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; -tree.Variable.prototype = { - eval: function (env) { - var variable, v, name = this.name; - - if (name.indexOf('@@') == 0) { - name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; - } - - if (variable = tree.find(env.frames, function (frame) { - if (v = frame.variable(name)) { - return v.value.eval(env); - } - })) { return variable } - else { - throw { type: 'Name', - message: "variable " + name + " is undefined", - filename: this.file, - index: this.index }; - } - } -}; - -})(require('../tree')); diff --git a/dashboard/doc/source/_static/.placeholder b/dashboard/doc/source/_static/.placeholder deleted file mode 100755 index e69de29b..00000000 diff --git a/dashboard/doc/source/_templates/.placeholder b/dashboard/doc/source/_templates/.placeholder deleted file mode 100755 index e69de29b..00000000 diff --git a/dashboard/doc/source/_theme/theme.conf b/dashboard/doc/source/_theme/theme.conf deleted file mode 100755 index e8748699..00000000 --- a/dashboard/doc/source/_theme/theme.conf +++ /dev/null @@ -1,2 +0,0 @@ -[theme] -inherit = default diff --git a/dashboard/doc/source/conf.py b/dashboard/doc/source/conf.py deleted file mode 100644 index be34f745..00000000 --- a/dashboard/doc/source/conf.py +++ /dev/null @@ -1,237 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2010 OpenStack Foundation. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# -# Portas documentation build configuration file, created by -# sphinx-quickstart on Tue February 28 13:50:15 2013. -# -# This file is execfile()'d with the current directory set to its containing -# dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import os -import sys - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path = [os.path.abspath('../../tabula'), - os.path.abspath('../..')] + sys.path - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', - 'sphinx.ext.intersphinx', - 'sphinx.ext.coverage', - 'sphinx.ext.pngmath', - 'sphinx.ext.ifconfig', - 'sphinx.ext.graphviz'] - -# Add any paths that contain templates here, relative to this directory. -templates_path = [] -if os.getenv('HUDSON_PUBLISH_DOCS'): - templates_path = ['_ga', '_templates'] -else: - templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'Tabula' -copyright = u'2013, Mirantis, Inc' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -from tabula.version import version_info as tabula_version -# The full version, including alpha/beta/rc tags. -release = tabula_version.version_string_with_vcs() -# The short X.Y version. -version = tabula_version.canonical_version_string() - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of documents that shouldn't be included in the build. -#unused_docs = [] - -# List of directories, relative to source directory, that shouldn't be searched -# for source files. -exclude_trees = ['api'] - -# The reST default role (for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -show_authors = True - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -modindex_common_prefix = ['tabula.'] - -# -- Options for man page output -------------------------------------------- - -# Grouping the document tree for man pages. -# List of tuples 'sourcefile', 'target', u'title', u'Authors name', 'manual' - -man_pages = [] - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -html_theme_path = ["."] -html_theme = '_theme' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = ['_theme'] - -# The name for this set of Sphinx documents. If None, it defaults to -# "<project> v<release> documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' -git_cmd = "git log --pretty=format:'%ad, commit %h' --date=local -n1" -html_last_updated_fmt = os.popen(git_cmd).read() - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -html_use_modindex = False - -# If false, no index is generated. -html_use_index = False - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a <link> tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = '' - -# Output file base name for HTML help builder. -htmlhelp_basename = 'tabuladoc' - - -# -- Options for LaTeX output ------------------------------------------------ - -# The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' - -# The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, -# documentclass [howto/manual]). -latex_documents = [ - ('index', 'Tabula.tex', u'Tabula Documentation', - u'Keero Team', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# Additional stuff for the LaTeX preamble. -#latex_preamble = '' - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_use_modindex = True - -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'python': ('http://docs.python.org/', None)} diff --git a/dashboard/doc/source/index.rst b/dashboard/doc/source/index.rst deleted file mode 100644 index 0de7d53d..00000000 --- a/dashboard/doc/source/index.rst +++ /dev/null @@ -1,65 +0,0 @@ -.. - Copyright 2010 OpenStack Foundation - All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); you may - not use this file except in compliance with the License. You may obtain - a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - License for the specific language governing permissions and limitations - under the License. - -============================================== -Welcome to Tabula, the Keero Project Web UI! -============================================== - -Tabula is a project that provides Web UI to Keero Project. - -This document describes Tabula for contributors of the project, and assumes -that you are already familiar with Portas from an `end-user perspective`_. - -.. _`end-user perspective`: http://keero.mirantis.com/ - -This documentation is generated by the Sphinx toolkit and lives in the source -tree. - -Installation Guide -================== -Install -------- -1. Check out sources to some directory (<home>/keero):: - - user@work:~/$ git clone ssh://<user>@gerrit.mirantis.com:29418/keero/keero.git - -2. Install virtualenv:: - - user@work:~/$ cd keero/tabula && sudo python ./tools/install_venv.py - -Configure ---------- -1. Copy configuration file from template:: - - user@work:~/$ cp keero/tabula/tabula/local/local_settings.py.example keero/tabula/tabula/local/local_settings.py - -2. Open configuration file for editing:: - - user@work:~/$ cd keero/tabula/tabula/local/ && nano local_settings.py - -2. Configure according to you environment:: - - ... - SECRET_KEY = 'some_random_value' - ... - OPENSTACK_HOST = "localhost" - ... - -Run ----- -Run Tabula in virtualenv:: - - user@work:~/$ cd keero/tabula && sudo ./tools/with_venv.sh python manage.py runserver 0.0.0.0:8080 diff --git a/dashboard/glazierdashboard/__init__.py b/dashboard/glazierdashboard/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/dashboard/glazierdashboard/local/__init__.py b/dashboard/glazierdashboard/local/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/dashboard/glazierdashboard/local/local_settings.py.example b/dashboard/glazierdashboard/local/local_settings.py.example deleted file mode 100644 index d841e6a2..00000000 --- a/dashboard/glazierdashboard/local/local_settings.py.example +++ /dev/null @@ -1,147 +0,0 @@ -import os - -from django.utils.translation import ugettext_lazy as _ - -DEBUG = True -TEMPLATE_DEBUG = DEBUG - -# Set SSL proxy settings: -# For Django 1.4+ pass this header from the proxy after terminating the SSL, -# and don't forget to strip it from the client's request. -# For more information see: -# https://docs.djangoproject.com/en/1.4/ref/settings/#secure-proxy-ssl-header -# SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https') - -# Specify a regular expression to validate user passwords. -# HORIZON_CONFIG = { -# "password_validator": { -# "regex": '.*', -# "help_text": _("Your password does not meet the requirements.") -# }, -# 'help_url': "http://docs.openstack.org" -# } - -LOCAL_PATH = os.path.dirname(os.path.abspath(__file__)) - -# Set custom secret key: -# You can either set it to a specific value or you can let horizion generate a -# default secret key that is unique on this machine, e.i. regardless of the -# amount of Python WSGI workers (if used behind Apache+mod_wsgi): However, there -# may be situations where you would want to set this explicitly, e.g. when -# multiple dashboard instances are distributed on different machines (usually -# behind a load-balancer). Either you have to make sure that a session gets all -# requests routed to the same dashboard instance or you set the same SECRET_KEY -# for all of them. -# from horizon.utils import secret_key -# SECRET_KEY = secret_key.generate_or_read_from_file(os.path.join(LOCAL_PATH, '.secret_key_store')) - -# We recommend you use memcached for development; otherwise after every reload -# of the django development server, you will have to login again. To use -# memcached set CACHE_BACKED to something like 'memcached://127.0.0.1:11211/' -CACHE_BACKEND = 'locmem://' - -# Send email to the console by default -EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' -# Or send them to /dev/null -#EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend' - -# Configure these for your outgoing email host -# EMAIL_HOST = 'smtp.my-company.com' -# EMAIL_PORT = 25 -# EMAIL_HOST_USER = 'djangomail' -# EMAIL_HOST_PASSWORD = 'top-secret!' - -# For multiple regions uncomment this configuration, and add (endpoint, title). -# AVAILABLE_REGIONS = [ -# ('http://cluster1.example.com:5000/v2.0', 'cluster1'), -# ('http://cluster2.example.com:5000/v2.0', 'cluster2'), -# ] - -OPENSTACK_HOST = "127.0.0.1" -OPENSTACK_KEYSTONE_URL = "http://%s:5000/v2.0" % OPENSTACK_HOST -OPENSTACK_KEYSTONE_DEFAULT_ROLE = "Member" - -# Disable SSL certificate checks (useful for self-signed certificates): -# OPENSTACK_SSL_NO_VERIFY = True - -# The OPENSTACK_KEYSTONE_BACKEND settings can be used to identify the -# capabilities of the auth backend for Keystone. -# If Keystone has been configured to use LDAP as the auth backend then set -# can_edit_user to False and name to 'ldap'. -# -# TODO(tres): Remove these once Keystone has an API to identify auth backend. -OPENSTACK_KEYSTONE_BACKEND = { - 'name': 'native', - 'can_edit_user': True -} - -OPENSTACK_HYPERVISOR_FEATURES = { - 'can_set_mount_point': True -} - -# OPENSTACK_ENDPOINT_TYPE specifies the endpoint type to use for the endpoints -# in the Keystone service catalog. Use this setting when Horizon is running -# external to the OpenStack environment. The default is 'internalURL'. -#OPENSTACK_ENDPOINT_TYPE = "publicURL" - -# The number of objects (Swift containers/objects or images) to display -# on a single page before providing a paging element (a "more" link) -# to paginate results. -API_RESULT_LIMIT = 1000 -API_RESULT_PAGE_SIZE = 20 - -# The timezone of the server. This should correspond with the timezone -# of your entire OpenStack installation, and hopefully be in UTC. -TIME_ZONE = "UTC" - -LOGGING = { - 'version': 1, - # When set to True this will disable all logging except - # for loggers specified in this configuration dictionary. Note that - # if nothing is specified here and disable_existing_loggers is True, - # django.db.backends will still log unless it is disabled explicitly. - 'disable_existing_loggers': False, - 'handlers': { - 'null': { - 'level': 'DEBUG', - 'class': 'django.utils.log.NullHandler', - }, - 'console': { - # Set the level to "DEBUG" for verbose output logging. - 'level': 'INFO', - 'class': 'logging.StreamHandler', - }, - }, - 'loggers': { - # Logging from django.db.backends is VERY verbose, send to null - # by default. - 'django.db.backends': { - 'handlers': ['null'], - 'propagate': False, - }, - 'horizon': { - 'handlers': ['console'], - 'propagate': False, - }, - 'openstack_dashboard': { - 'handlers': ['console'], - 'propagate': False, - }, - 'novaclient': { - 'handlers': ['console'], - 'propagate': False, - }, - 'keystoneclient': { - 'handlers': ['console'], - 'propagate': False, - }, - 'glanceclient': { - 'handlers': ['console'], - 'propagate': False, - }, - 'nose.plugins.manager': { - 'handlers': ['console'], - 'propagate': False, - } - } -} diff --git a/dashboard/glazierdashboard/models.py b/dashboard/glazierdashboard/models.py deleted file mode 100644 index 1b3d5f9e..00000000 --- a/dashboard/glazierdashboard/models.py +++ /dev/null @@ -1,3 +0,0 @@ -""" -Stub file to work around django bug: https://code.djangoproject.com/ticket/7198 -""" diff --git a/dashboard/glazierdashboard/openstack/__init__.py b/dashboard/glazierdashboard/openstack/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/dashboard/glazierdashboard/openstack/common/__init__.py b/dashboard/glazierdashboard/openstack/common/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/dashboard/glazierdashboard/openstack/common/importutils.py b/dashboard/glazierdashboard/openstack/common/importutils.py deleted file mode 100644 index 3bd277f4..00000000 --- a/dashboard/glazierdashboard/openstack/common/importutils.py +++ /dev/null @@ -1,67 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Import related utilities and helper functions. -""" - -import sys -import traceback - - -def import_class(import_str): - """Returns a class from a string including module and class""" - mod_str, _sep, class_str = import_str.rpartition('.') - try: - __import__(mod_str) - return getattr(sys.modules[mod_str], class_str) - except (ValueError, AttributeError): - raise ImportError('Class %s cannot be found (%s)' % - (class_str, - traceback.format_exception(*sys.exc_info()))) - - -def import_object(import_str, *args, **kwargs): - """Import a class and return an instance of it.""" - return import_class(import_str)(*args, **kwargs) - - -def import_object_ns(name_space, import_str, *args, **kwargs): - """ - Import a class and return an instance of it, first by trying - to find the class in a default namespace, then failing back to - a full path if not found in the default namespace. - """ - import_value = "%s.%s" % (name_space, import_str) - try: - return import_class(import_value)(*args, **kwargs) - except ImportError: - return import_class(import_str)(*args, **kwargs) - - -def import_module(import_str): - """Import a module.""" - __import__(import_str) - return sys.modules[import_str] - - -def try_import(import_str, default=None): - """Try to import a module and if it fails return default.""" - try: - return import_module(import_str) - except ImportError: - return default diff --git a/dashboard/glazierdashboard/openstack/common/setup.py b/dashboard/glazierdashboard/openstack/common/setup.py deleted file mode 100644 index dec74fd0..00000000 --- a/dashboard/glazierdashboard/openstack/common/setup.py +++ /dev/null @@ -1,367 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack Foundation. -# Copyright 2012-2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Utilities with minimum-depends for use in setup.py -""" - -import email -import os -import re -import subprocess -import sys - -from setuptools.command import sdist - - -def parse_mailmap(mailmap='.mailmap'): - mapping = {} - if os.path.exists(mailmap): - with open(mailmap, 'r') as fp: - for l in fp: - try: - canonical_email, alias = re.match( - r'[^#]*?(<.+>).*(<.+>).*', l).groups() - except AttributeError: - continue - mapping[alias] = canonical_email - return mapping - - -def _parse_git_mailmap(git_dir, mailmap='.mailmap'): - mailmap = os.path.join(os.path.dirname(git_dir), mailmap) - return parse_mailmap(mailmap) - - -def canonicalize_emails(changelog, mapping): - """Takes in a string and an email alias mapping and replaces all - instances of the aliases in the string with their real email. - """ - for alias, email_address in mapping.iteritems(): - changelog = changelog.replace(alias, email_address) - return changelog - - -# Get requirements from the first file that exists -def get_reqs_from_files(requirements_files): - for requirements_file in requirements_files: - if os.path.exists(requirements_file): - with open(requirements_file, 'r') as fil: - return fil.read().split('\n') - return [] - - -def parse_requirements(requirements_files=['requirements.txt', - 'tools/pip-requires']): - requirements = [] - for line in get_reqs_from_files(requirements_files): - # For the requirements list, we need to inject only the portion - # after egg= so that distutils knows the package it's looking for - # such as: - # -e git://github.com/openstack/nova/master#egg=nova - if re.match(r'\s*-e\s+', line): - requirements.append(re.sub(r'\s*-e\s+.*#egg=(.*)$', r'\1', - line)) - # such as: - # http://github.com/openstack/nova/zipball/master#egg=nova - elif re.match(r'\s*https?:', line): - requirements.append(re.sub(r'\s*https?:.*#egg=(.*)$', r'\1', - line)) - # -f lines are for index locations, and don't get used here - elif re.match(r'\s*-f\s+', line): - pass - # argparse is part of the standard library starting with 2.7 - # adding it to the requirements list screws distro installs - elif line == 'argparse' and sys.version_info >= (2, 7): - pass - else: - requirements.append(line) - - return requirements - - -def parse_dependency_links(requirements_files=['requirements.txt', - 'tools/pip-requires']): - dependency_links = [] - # dependency_links inject alternate locations to find packages listed - # in requirements - for line in get_reqs_from_files(requirements_files): - # skip comments and blank lines - if re.match(r'(\s*#)|(\s*$)', line): - continue - # lines with -e or -f need the whole line, minus the flag - if re.match(r'\s*-[ef]\s+', line): - dependency_links.append(re.sub(r'\s*-[ef]\s+', '', line)) - # lines that are only urls can go in unmolested - elif re.match(r'\s*https?:', line): - dependency_links.append(line) - return dependency_links - - -def _run_shell_command(cmd, throw_on_error=False): - if os.name == 'nt': - output = subprocess.Popen(["cmd.exe", "/C", cmd], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - else: - output = subprocess.Popen(["/bin/sh", "-c", cmd], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - out = output.communicate() - if output.returncode and throw_on_error: - raise Exception("%s returned %d" % cmd, output.returncode) - if len(out) == 0: - return None - if len(out[0].strip()) == 0: - return None - return out[0].strip() - - -def _get_git_directory(): - parent_dir = os.path.dirname(__file__) - while True: - git_dir = os.path.join(parent_dir, '.git') - if os.path.exists(git_dir): - return git_dir - parent_dir, child = os.path.split(parent_dir) - if not child: # reached to root dir - return None - - -def write_git_changelog(): - """Write a changelog based on the git changelog.""" - new_changelog = 'ChangeLog' - git_dir = _get_git_directory() - if not os.getenv('SKIP_WRITE_GIT_CHANGELOG'): - if git_dir: - git_log_cmd = 'git --git-dir=%s log' % git_dir - changelog = _run_shell_command(git_log_cmd) - mailmap = _parse_git_mailmap(git_dir) - with open(new_changelog, "w") as changelog_file: - changelog_file.write(canonicalize_emails(changelog, mailmap)) - else: - open(new_changelog, 'w').close() - - -def generate_authors(): - """Create AUTHORS file using git commits.""" - jenkins_email = 'jenkins@review.(openstack|stackforge).org' - old_authors = 'AUTHORS.in' - new_authors = 'AUTHORS' - git_dir = _get_git_directory() - if not os.getenv('SKIP_GENERATE_AUTHORS'): - if git_dir: - # don't include jenkins email address in AUTHORS file - git_log_cmd = ("git --git-dir=" + git_dir + - " log --format='%aN <%aE>' | sort -u | " - "egrep -v '" + jenkins_email + "'") - changelog = _run_shell_command(git_log_cmd) - signed_cmd = ("git log --git-dir=" + git_dir + - " | grep -i Co-authored-by: | sort -u") - signed_entries = _run_shell_command(signed_cmd) - if signed_entries: - new_entries = "\n".join( - [signed.split(":", 1)[1].strip() - for signed in signed_entries.split("\n") if signed]) - changelog = "\n".join((changelog, new_entries)) - mailmap = _parse_git_mailmap(git_dir) - with open(new_authors, 'w') as new_authors_fh: - new_authors_fh.write(canonicalize_emails(changelog, mailmap)) - if os.path.exists(old_authors): - with open(old_authors, "r") as old_authors_fh: - new_authors_fh.write('\n' + old_authors_fh.read()) - else: - open(new_authors, 'w').close() - - -_rst_template = """%(heading)s -%(underline)s - -.. automodule:: %(module)s - :members: - :undoc-members: - :show-inheritance: -""" - - -def get_cmdclass(): - """Return dict of commands to run from setup.py.""" - - cmdclass = dict() - - def _find_modules(arg, dirname, files): - for filename in files: - if filename.endswith('.py') and filename != '__init__.py': - arg["%s.%s" % (dirname.replace('/', '.'), - filename[:-3])] = True - - class LocalSDist(sdist.sdist): - """Builds the ChangeLog and Authors files from VC first.""" - - def run(self): - write_git_changelog() - generate_authors() - # sdist.sdist is an old style class, can't use super() - sdist.sdist.run(self) - - cmdclass['sdist'] = LocalSDist - - # If Sphinx is installed on the box running setup.py, - # enable setup.py to build the documentation, otherwise, - # just ignore it - try: - from sphinx.setup_command import BuildDoc - - class LocalBuildDoc(BuildDoc): - - builders = ['html', 'man'] - - def generate_autoindex(self): - print "**Autodocumenting from %s" % os.path.abspath(os.curdir) - modules = {} - option_dict = self.distribution.get_option_dict('build_sphinx') - source_dir = os.path.join(option_dict['source_dir'][1], 'api') - if not os.path.exists(source_dir): - os.makedirs(source_dir) - for pkg in self.distribution.packages: - if '.' not in pkg: - os.path.walk(pkg, _find_modules, modules) - module_list = modules.keys() - module_list.sort() - autoindex_filename = os.path.join(source_dir, 'autoindex.rst') - with open(autoindex_filename, 'w') as autoindex: - autoindex.write(""".. toctree:: - :maxdepth: 1 - -""") - for module in module_list: - output_filename = os.path.join(source_dir, - "%s.rst" % module) - heading = "The :mod:`%s` Module" % module - underline = "=" * len(heading) - values = dict(module=module, heading=heading, - underline=underline) - - print "Generating %s" % output_filename - with open(output_filename, 'w') as output_file: - output_file.write(_rst_template % values) - autoindex.write(" %s.rst\n" % module) - - def run(self): - if not os.getenv('SPHINX_DEBUG'): - self.generate_autoindex() - - for builder in self.builders: - self.builder = builder - self.finalize_options() - self.project = self.distribution.get_name() - self.version = self.distribution.get_version() - self.release = self.distribution.get_version() - BuildDoc.run(self) - - class LocalBuildLatex(LocalBuildDoc): - builders = ['latex'] - - cmdclass['build_sphinx'] = LocalBuildDoc - cmdclass['build_sphinx_latex'] = LocalBuildLatex - except ImportError: - pass - - return cmdclass - - -def _get_revno(git_dir): - """Return the number of commits since the most recent tag. - - We use git-describe to find this out, but if there are no - tags then we fall back to counting commits since the beginning - of time. - """ - describe = _run_shell_command( - "git --git-dir=%s describe --always" % git_dir) - if "-" in describe: - return describe.rsplit("-", 2)[-2] - - # no tags found - revlist = _run_shell_command( - "git --git-dir=%s rev-list --abbrev-commit HEAD" % git_dir) - return len(revlist.splitlines()) - - -def _get_version_from_git(pre_version): - """Return a version which is equal to the tag that's on the current - revision if there is one, or tag plus number of additional revisions - if the current revision has no tag.""" - - git_dir = _get_git_directory() - if git_dir: - if pre_version: - try: - return _run_shell_command( - "git --git-dir=" + git_dir + " describe --exact-match", - throw_on_error=True).replace('-', '.') - except Exception: - sha = _run_shell_command( - "git --git-dir=" + git_dir + " log -n1 --pretty=format:%h") - return "%s.a%s.g%s" % (pre_version, _get_revno(git_dir), sha) - else: - return _run_shell_command( - "git --git-dir=" + git_dir + " describe --always").replace( - '-', '.') - return None - - -def _get_version_from_pkg_info(package_name): - """Get the version from PKG-INFO file if we can.""" - try: - pkg_info_file = open('PKG-INFO', 'r') - except (IOError, OSError): - return None - try: - pkg_info = email.message_from_file(pkg_info_file) - except email.MessageError: - return None - # Check to make sure we're in our own dir - if pkg_info.get('Name', None) != package_name: - return None - return pkg_info.get('Version', None) - - -def get_version(package_name, pre_version=None): - """Get the version of the project. First, try getting it from PKG-INFO, if - it exists. If it does, that means we're in a distribution tarball or that - install has happened. Otherwise, if there is no PKG-INFO file, pull the - version from git. - - We do not support setup.py version sanity in git archive tarballs, nor do - we support packagers directly sucking our git repo into theirs. We expect - that a source tarball be made from our git repo - or that if someone wants - to make a source tarball from a fork of our repo with additional tags in it - that they understand and desire the results of doing that. - """ - version = os.environ.get("OSLO_PACKAGE_VERSION", None) - if version: - return version - version = _get_version_from_pkg_info(package_name) - if version: - return version - version = _get_version_from_git(pre_version) - if version: - return version - raise Exception("Versioning for this project requires either an sdist" - " tarball, or access to an upstream git repository.") diff --git a/dashboard/glazierdashboard/openstack/common/version.py b/dashboard/glazierdashboard/openstack/common/version.py deleted file mode 100644 index b2d4a79b..00000000 --- a/dashboard/glazierdashboard/openstack/common/version.py +++ /dev/null @@ -1,94 +0,0 @@ - -# Copyright 2012 OpenStack Foundation -# Copyright 2012-2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Utilities for consuming the version from pkg_resources. -""" - -import pkg_resources - - -class VersionInfo(object): - - def __init__(self, package): - """Object that understands versioning for a package - :param package: name of the python package, such as glance, or - python-glanceclient - """ - self.package = package - self.release = None - self.version = None - self._cached_version = None - - def __str__(self): - """Make the VersionInfo object behave like a string.""" - return self.version_string() - - def __repr__(self): - """Include the name.""" - return "VersionInfo(%s:%s)" % (self.package, self.version_string()) - - def _get_version_from_pkg_resources(self): - """Get the version of the package from the pkg_resources record - associated with the package.""" - try: - requirement = pkg_resources.Requirement.parse(self.package) - provider = pkg_resources.get_provider(requirement) - return provider.version - except pkg_resources.DistributionNotFound: - # The most likely cause for this is running tests in a tree - # produced from a tarball where the package itself has not been - # installed into anything. Revert to setup-time logic. - from tabula.openstack.common import setup - return setup.get_version(self.package) - - def release_string(self): - """Return the full version of the package including suffixes indicating - VCS status. - """ - if self.release is None: - self.release = self._get_version_from_pkg_resources() - - return self.release - - def version_string(self): - """Return the short version minus any alpha/beta tags.""" - if self.version is None: - parts = [] - for part in self.release_string().split('.'): - if part[0].isdigit(): - parts.append(part) - else: - break - self.version = ".".join(parts) - - return self.version - - # Compatibility functions - canonical_version_string = version_string - version_string_with_vcs = release_string - - def cached_version_string(self, prefix=""): - """Generate an object which will expand in a string context to - the results of version_string(). We do this so that don't - call into pkg_resources every time we start up a program when - passing version information into the CONF constructor, but - rather only do the calculation when and if a version is requested - """ - if not self._cached_version: - self._cached_version = "%s%s" % (prefix, - self.version_string()) - return self._cached_version diff --git a/dashboard/glazierdashboard/settings.py b/dashboard/glazierdashboard/settings.py deleted file mode 100644 index e2bb24a2..00000000 --- a/dashboard/glazierdashboard/settings.py +++ /dev/null @@ -1,148 +0,0 @@ -import logging -import os -import sys - -from openstack_dashboard import exceptions - -ROOT_PATH = os.path.dirname(os.path.abspath(__file__)) -BIN_DIR = os.path.abspath(os.path.join(ROOT_PATH, '..', 'bin')) - -if ROOT_PATH not in sys.path: - sys.path.append(ROOT_PATH) - -DEBUG = False -TEMPLATE_DEBUG = DEBUG - -SITE_BRANDING = 'OpenStack Dashboard' - -LOGIN_URL = '/auth/login/' -LOGOUT_URL = '/auth/logout/' -# LOGIN_REDIRECT_URL can be used as an alternative for -# HORIZON_CONFIG.user_home, if user_home is not set. -# Do not set it to '/home/', as this will cause circular redirect loop -LOGIN_REDIRECT_URL = '/' - -MEDIA_ROOT = os.path.abspath(os.path.join(ROOT_PATH, '..', 'media')) -MEDIA_URL = '/media/' -STATIC_ROOT = os.path.abspath(os.path.join(ROOT_PATH, '..', 'static')) -STATIC_URL = '/static/' -ADMIN_MEDIA_PREFIX = '/static/admin/' - -ROOT_URLCONF = 'openstack_dashboard.urls' - -HORIZON_CONFIG = { - 'dashboards': ('project', 'admin', 'settings',), - 'default_dashboard': 'project', - 'user_home': 'openstack_dashboard.views.get_user_home', - 'ajax_queue_limit': 10, - 'help_url': "http://docs.openstack.org", - 'exceptions': {'recoverable': exceptions.RECOVERABLE, - 'not_found': exceptions.NOT_FOUND, - 'unauthorized': exceptions.UNAUTHORIZED}, - 'customization_module': 'tabula.overrides' -} - - -MIDDLEWARE_CLASSES = ( - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'horizon.middleware.HorizonMiddleware', - 'django.middleware.doc.XViewMiddleware', - 'django.middleware.locale.LocaleMiddleware', -) - -TEMPLATE_CONTEXT_PROCESSORS = ( - 'django.core.context_processors.debug', - 'django.core.context_processors.i18n', - 'django.core.context_processors.request', - 'django.core.context_processors.media', - 'django.core.context_processors.static', - 'django.contrib.messages.context_processors.messages', - 'horizon.context_processors.horizon', -) - -TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', - 'horizon.loaders.TemplateLoader' -) - -TEMPLATE_DIRS = ( - os.path.join(ROOT_PATH, 'templates'), -) - -STATICFILES_FINDERS = ( - 'compressor.finders.CompressorFinder', - 'django.contrib.staticfiles.finders.AppDirectoriesFinder', -) - -less_binary = os.path.join(BIN_DIR, 'less', 'lessc') -COMPRESS_PRECOMPILERS = ( - ('text/less', (less_binary + ' {infile} {outfile}')), -) - -COMPRESS_CSS_FILTERS = ( - 'compressor.filters.css_default.CssAbsoluteFilter', -) - -COMPRESS_ENABLED = True -COMPRESS_OUTPUT_DIR = 'windc' -COMPRESS_CSS_HASHING_METHOD = 'hash' -COMPRESS_PARSER = 'compressor.parser.HtmlParser' - -INSTALLED_APPS = ( - 'openstack_dashboard', - 'django.contrib.contenttypes', - 'django.contrib.auth', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'django.contrib.humanize', - 'compressor', - 'horizon', - 'openstack_dashboard.dashboards.project', - 'openstack_dashboard.dashboards.admin', - 'openstack_dashboard.dashboards.settings', - 'openstack_auth' -) - -TEST_RUNNER = 'django_nose.NoseTestSuiteRunner' -AUTHENTICATION_BACKENDS = ('openstack_auth.backend.KeystoneBackend',) -MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage' - -SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' -SESSION_COOKIE_HTTPONLY = True -SESSION_EXPIRE_AT_BROWSER_CLOSE = True -SESSION_COOKIE_SECURE = False - -gettext_noop = lambda s: s -LANGUAGES = ( - ('en', gettext_noop('English')), - ('it', gettext_noop('Italiano')), - ('es', gettext_noop('Spanish')), - ('fr', gettext_noop('French')), - ('ja', gettext_noop('Japanese')), - ('pt', gettext_noop('Portuguese')), - ('pl', gettext_noop('Polish')), - ('zh-cn', gettext_noop('Simplified Chinese')), - ('zh-tw', gettext_noop('Traditional Chinese')), -) -LANGUAGE_CODE = 'en' -USE_I18N = True -USE_L10N = True -USE_TZ = True - -OPENSTACK_KEYSTONE_DEFAULT_ROLE = 'Member' - -DEFAULT_EXCEPTION_REPORTER_FILTER = 'horizon.exceptions.HorizonReporterFilter' - -try: - from local.local_settings import * -except ImportError: - logging.warning("No local_settings file found.") - -if DEBUG: - logging.basicConfig(level=logging.DEBUG) diff --git a/dashboard/glazierdashboard/tabula/__init__.py b/dashboard/glazierdashboard/tabula/__init__.py deleted file mode 100644 index eb97e8c1..00000000 --- a/dashboard/glazierdashboard/tabula/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. \ No newline at end of file diff --git a/dashboard/glazierdashboard/tabula/api.py b/dashboard/glazierdashboard/tabula/api.py deleted file mode 100644 index 03130d0e..00000000 --- a/dashboard/glazierdashboard/tabula/api.py +++ /dev/null @@ -1,211 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import logging - -from glazierclient.v1.client import Client as glazier_client - -log = logging.getLogger(__name__) - - -def glazierclient(request): - url = "http://127.0.0.1:8082" - log.debug('glazierclient connection created using token "%s" and url "%s"' - % (request.user.token, url)) - return glazier_client(endpoint=url, token=request.user.token.token['id']) - - -def environment_create(request, parameters): - env = glazierclient(request).environments.create(parameters.get('name', '')) - log.debug('Environment::Create {0}'.format(env)) - return env - - -def environment_delete(request, environment_id): - result = glazierclient(request).environments.delete(environment_id) - log.debug('Environment::Delete Id:{0}'.format(environment_id)) - return result - - -def environment_get(request, environment_id): - env = glazierclient(request).environments.get(environment_id) - log.debug('Environment::Get {0}'.format(env)) - return env - - -def environments_list(request): - log.debug('Environment::List') - return glazierclient(request).environments.list() - - -def environment_deploy(request, environment_id): - sessions = glazierclient(request).sessions.list(environment_id) - for session in sessions: - if session.state == 'open': - session_id = session.id - if not session_id: - return "Sorry, nothing to deploy." - log.debug('Obtained session with Id: {0}'.format(session_id)) - result = glazierclient(request).sessions.deploy(environment_id, session_id) - log.debug('Environment with Id: {0} deployed in session ' - 'with Id: {1}'.format(environment_id, session_id)) - return result - - -def service_create(request, environment_id, parameters): - session_id = None - sessions = glazierclient(request).sessions.list(environment_id) - - for s in sessions: - if s.state == 'open': - session_id = s.id - else: - glazierclient(request).sessions.delete(environment_id, s.id) - - if session_id is None: - session_id = glazierclient(request).sessions.configure(environment_id).id - - if parameters['service_type'] == 'Active Directory': - service = glazierclient(request)\ - .activeDirectories\ - .create(environment_id, session_id, parameters) - else: - service = glazierclient(request)\ - .webServers.create(environment_id, session_id, parameters) - - log.debug('Service::Create {0}'.format(service)) - return service - - -def get_time(obj): - return obj.updated - - -def services_list(request, environment_id): - services = [] - session_id = None - sessions = glazierclient(request).sessions.list(environment_id) - for s in sessions: - session_id = s.id - - if session_id: - services = glazierclient(request).activeDirectories.\ - list(environment_id, session_id) - services += glazierclient(request).webServers.\ - list(environment_id, session_id) - - for i in range(len(services)): - reports = glazierclient(request).sessions. \ - reports(environment_id, session_id, - services[i].id) - - for report in reports: - services[i].operation = report.text - - log.debug('Service::List') - return services - - -def get_active_directories(request, environment_id): - services = [] - session_id = None - sessions = glazierclient(request).sessions.list(environment_id) - - for s in sessions: - session_id = s.id - - if session_id: - services = glazierclient(request)\ - .activeDirectories\ - .list(environment_id, session_id) - - log.debug('Service::Active Directories::List') - return services - - -def service_get(request, environment_id, service_id): - services = services_list(request, environment_id) - - for service in services: - if service.id == service_id: - log.debug('Service::Get {0}'.format(service)) - return service - - -def get_data_center_id_for_service(request, service_id): - environments = environments_list(request) - - for environment in environments: - services = services_list(request, environment.id) - for service in services: - if service.id == service_id: - return environment.id - - -def get_service_datails(request, service_id): - environments = environments_list(request) - services = [] - for environment in environments: - services += services_list(request, environment.id) - - for service in services: - if service.id == service_id: - return service - - -def get_status_message_for_service(request, service_id): - environment_id = get_data_center_id_for_service(request, service_id) - session_id = None - sessions = glazierclient(request).sessions.list(environment_id) - - for s in sessions: - session_id = s.id - - if session_id: - reports = glazierclient(request).sessions.\ - reports(environment_id, session_id, service_id) - - result = 'Initialization.... \n' - for report in reports: - result += ' ' + str(report.text) + '\n' - - return result - - -def service_delete(request, environment_id, service_id): - log.debug('Service::Remove EnvId: {0} ' - 'SrvId: {1}'.format(environment_id, service_id)) - - services = services_list(request, environment_id) - - session_id = None - sessions = glazierclient(request).sessions.list(environment_id) - for session in sessions: - if session.state == 'open': - session_id = session.id - - if session_id is None: - raise Exception("Sorry, you can not delete this service now.") - - for service in services: - if service.id is service_id: - if service.type is 'Active Directory': - glazierclient(request).activeDirectories.delete(environment_id, - session_id, - service_id) - elif service.type is 'IIS': - glazierclient(request).webServers.delete(environment_id, - session_id, - service_id) diff --git a/dashboard/glazierdashboard/tabula/forms.py b/dashboard/glazierdashboard/tabula/forms.py deleted file mode 100644 index 515488d9..00000000 --- a/dashboard/glazierdashboard/tabula/forms.py +++ /dev/null @@ -1,120 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import logging -import string - -from django import forms -from django.utils.translation import ugettext_lazy as _ -import re -from glazierdashboard.tabula import api - -log = logging.getLogger(__name__) - - -class PasswordField(forms.CharField): - # Setup the Field - def __init__(self, label, *args, **kwargs): - super(PasswordField, self).__init__(min_length=7, required=True, - label=label, - widget=forms.PasswordInput( - render_value=False), - *args, **kwargs) - - def clean(self, value): - - # Setup Our Lists of Characters and Numbers - characters = list(string.letters) - special_characters = '!@#$%^&*()_+|\/.,~?><:{}' - numbers = [str(i) for i in range(10)] - - # Assume False until Proven Otherwise - numCheck = False - charCheck = False - specCharCheck = False - - # Loop until we Match - for char in value: - if not charCheck: - if char in characters: - charCheck = True - if not specCharCheck: - if char in special_characters: - specCharCheck = True - if not numCheck: - if char in numbers: - numCheck = True - if numCheck and charCheck and specCharCheck: - break - - if not numCheck or not charCheck or not specCharCheck: - raise forms.ValidationError(u'Your password must include at least \ - one letter, at least one number and \ - at least one special character.') - - return super(PasswordField, self).clean(value) - - -class WizardFormServiceType(forms.Form): - service = forms.ChoiceField(label=_('Service Type'), - choices=[ - ('Active Directory', 'Active Directory'), - ('IIS', 'Internet Information Services') - ]) - - -class WizardFormConfiguration(forms.Form): - 'The functions for this class will dynamically create in views.py' - pass - - -class WizardFormADConfiguration(forms.Form): - dc_name = forms.CharField(label=_('Domain Name'), - required=True) - - dc_count = forms.IntegerField(label=_('Instances Count'), - required=True, - min_value=1, - max_value=100, - initial=1) - - adm_password = PasswordField(_('Administrator password')) - - recovery_password = PasswordField(_('Recovery password')) - - def __init__(self, request, *args, **kwargs): - super(WizardFormADConfiguration, self).__init__(*args, **kwargs) - - -class WizardFormIISConfiguration(forms.Form): - iis_name = forms.CharField(label=_('IIS Server Name'), - required=True) - - adm_password = PasswordField(_('Administrator password')) - - iis_domain = forms.ChoiceField(label=_('Member of the Domain'), - required=False) - - def __init__(self, request, *args, **kwargs): - super(WizardFormIISConfiguration, self).__init__(*args, **kwargs) - - link = request.__dict__['META']['HTTP_REFERER'] - environment_id = re.search('tabula/(\S+)', link).group(0)[7:-1] - - domains = api.get_active_directories(request, environment_id) - - self.fields['iis_domain'].choices = [("", "")] + \ - [(domain.name, domain.name) - for domain in domains] diff --git a/dashboard/glazierdashboard/tabula/overrides.py b/dashboard/glazierdashboard/tabula/overrides.py deleted file mode 100644 index 849eaefc..00000000 --- a/dashboard/glazierdashboard/tabula/overrides.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import horizon - -from panel import tabula - -project = horizon.get_dashboard('project') -project.register(tabula) diff --git a/dashboard/glazierdashboard/tabula/panel.py b/dashboard/glazierdashboard/tabula/panel.py deleted file mode 100644 index 6acae86b..00000000 --- a/dashboard/glazierdashboard/tabula/panel.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import horizon -from django.utils.translation import ugettext_lazy as _ -from openstack_dashboard.dashboards.project import dashboard - - -class tabula(horizon.Panel): - name = _("Environments") - slug = 'tabula' - - -dashboard.Project.register(tabula) diff --git a/dashboard/glazierdashboard/tabula/tables.py b/dashboard/glazierdashboard/tabula/tables.py deleted file mode 100644 index 94eabd3b..00000000 --- a/dashboard/glazierdashboard/tabula/tables.py +++ /dev/null @@ -1,193 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import logging -import re - -from django.utils.translation import ugettext_lazy as _ -from horizon import messages -from horizon import tables -from glazierdashboard.tabula import api - - -LOG = logging.getLogger(__name__) - - -class CreateService(tables.LinkAction): - name = 'CreateService' - verbose_name = _('Create Service') - url = 'horizon:project:tabula:create' - classes = ('btn-launch', 'ajax-modal') - - def allowed(self, request, datum): - return True - - def action(self, request, service): - api.service_create(request, service) - - -class CreateEnvironment(tables.LinkAction): - name = 'CreateEnvironment' - verbose_name = _('Create Environment') - url = 'horizon:project:tabula:create_dc' - classes = ('btn-launch', 'ajax-modal') - - def allowed(self, request, datum): - return True - - def action(self, request, environment): - api.environment_create(request, environment) - - -class DeleteEnvironment(tables.BatchAction): - name = 'delete' - action_present = _('Delete') - action_past = _('Delete') - data_type_singular = _('Environment') - data_type_plural = _('Environment') - classes = ('btn-danger', 'btn-terminate') - - def allowed(self, request, datum): - return True - - def action(self, request, environment_id): - api.environment_delete(request, environment_id) - - -class DeleteService(tables.BatchAction): - name = 'delete' - action_present = _('Delete') - action_past = _('Delete') - data_type_singular = _('Service') - data_type_plural = _('Service') - classes = ('btn-danger', 'btn-terminate') - - def allowed(self, request, datum): - return True - - def action(self, request, service_id): - link = request.__dict__['META']['HTTP_REFERER'] - datacenter_id = re.search('tabula/(\S+)', link).group(0)[7:-1] - - try: - api.service_delete(request, datacenter_id, service_id) - except: - messages.error(request, _('Sorry, you can not delete this ' - 'service right now.')) - - -class DeployEnvironment(tables.BatchAction): - name = 'deploy' - action_present = _('Deploy') - action_past = _('Deploy') - data_type_singular = _('Environment') - data_type_plural = _('Environment') - classes = 'btn-launch' - - def allowed(self, request, datum): - return True - - def action(self, request, environment_id): - return api.environment_deploy(request, environment_id) - - -class ShowEnvironmentServices(tables.LinkAction): - name = 'edit' - verbose_name = _('Services') - url = 'horizon:project:tabula:services' - - def allowed(self, request, instance): - return True - - -class UpdateEnvironmentRow(tables.Row): - ajax = True - - def get_data(self, request, environment_id): - return api.environment_get(request, environment_id) - - -class UpdateServiceRow(tables.Row): - ajax = True - - def get_data(self, request, service_id): - - link = request.__dict__['META']['HTTP_REFERER'] - environment_id = re.search('tabula/(\S+)', link).group(0)[77:-1] - - service = api.service_get(request, environment_id, service_id) - - return service - - -STATUS_DISPLAY_CHOICES = ( - ('draft', 'Ready to deploy'), - ('pending', 'Wait for configuration'), - ('inprogress', 'Deploy in progress'), - ('finished', 'Active') -) - - -class EnvironmentsTable(tables.DataTable): - STATUS_CHOICES = ( - (None, True), - ('Ready to deploy', True), - ('Active', True) - ) - - name = tables.Column('name', - link=('horizon:project:tabula:services'), - verbose_name=_('Name')) - - status = tables.Column('status', verbose_name=_('Status'), - status=True, - status_choices=STATUS_CHOICES, - display_choices=STATUS_DISPLAY_CHOICES) - - class Meta: - name = 'tabula' - verbose_name = _('Environments') - row_class = UpdateEnvironmentRow - status_columns = ['status'] - table_actions = (CreateEnvironment,) - row_actions = (ShowEnvironmentServices, DeleteEnvironment, - DeployEnvironment) - - -class ServicesTable(tables.DataTable): - STATUS_CHOICES = ( - (None, True), - ('Ready to deploy', True), - ('Active', True) - ) - - name = tables.Column('name', verbose_name=_('Name'), - link=('horizon:project:tabula:service_details')) - - _type = tables.Column('service_type', verbose_name=_('Type')) - - status = tables.Column('status', verbose_name=_('Status'), - status=True, - status_choices=STATUS_CHOICES, - display_choices=STATUS_DISPLAY_CHOICES) - - operation = tables.Column('operation', verbose_name=_('Operation')) - - class Meta: - name = 'services' - verbose_name = _('Services') - row_class = UpdateServiceRow - status_columns = ['status'] - table_actions = (CreateService,) diff --git a/dashboard/glazierdashboard/tabula/tabs.py b/dashboard/glazierdashboard/tabula/tabs.py deleted file mode 100644 index a42683d0..00000000 --- a/dashboard/glazierdashboard/tabula/tabs.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from django.utils.translation import ugettext_lazy as _ - -from horizon import exceptions -from horizon import tabs -import logging - -from glazierdashboard.tabula import api - - -LOG = logging.getLogger(__name__) - - -class OverviewTab(tabs.Tab): - name = _("Service") - slug = "_service" - template_name = '_services.html' - - def get_context_data(self, request): - data = self.tab_group.kwargs['service'] - - return {"service_name": data.name, - "service_status": data.status, - "service_type": data.service_type, - "service_domain": data.domain} - - -class LogsTab(tabs.Tab): - name = _("Logs") - slug = "_logs" - template_name = '_service_logs.html' - - def get_context_data(self, request): - data = self.tab_group.kwargs['service'] - - reports = api.get_status_message_for_service(request, data.id) - - return {"reports": reports} - - -class ServicesTabs(tabs.TabGroup): - slug = "services_details" - tabs = (OverviewTab, LogsTab) - sticky = True diff --git a/dashboard/glazierdashboard/tabula/urls.py b/dashboard/glazierdashboard/tabula/urls.py deleted file mode 100644 index 7e273fb6..00000000 --- a/dashboard/glazierdashboard/tabula/urls.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from django.conf.urls.defaults import patterns, url - -from .views import IndexView, Services, CreateEnvironmentView, DetailServiceView -from .views import Wizard -from .forms import WizardFormServiceType, WizardFormConfiguration - -VIEW_MOD = 'openstack_dashboard.dashboards.project.tabula.views' - -urlpatterns = patterns(VIEW_MOD, - url(r'^$', IndexView.as_view(), name='index'), - url(r'^create$', - Wizard.as_view([WizardFormServiceType, - WizardFormConfiguration]), - name='create'), - url(r'^create_dc$', CreateEnvironmentView.as_view(), - name='create_dc'), - url(r'^(?P<environment_id>[^/]+)/$', - Services.as_view(), name='services'), - url(r'^(?P<service_id>[^/]+)/details$', - DetailServiceView.as_view(), - name='service_details')) diff --git a/dashboard/glazierdashboard/tabula/views.py b/dashboard/glazierdashboard/tabula/views.py deleted file mode 100644 index 9e4308e2..00000000 --- a/dashboard/glazierdashboard/tabula/views.py +++ /dev/null @@ -1,204 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import logging -import re - -from django.views import generic -from django.core.urlresolvers import reverse -from django.utils.translation import ugettext_lazy as _ -from django.contrib.formtools.wizard.views import SessionWizardView - -from horizon import exceptions -from horizon import tabs -from horizon import tables -from horizon import workflows -from horizon.forms.views import ModalFormMixin - -from glazierdashboard.tabula import api - -from .tables import EnvironmentsTable, ServicesTable -from .workflows import CreateEnvironment -from .tabs import ServicesTabs -from .forms import (WizardFormADConfiguration, WizardFormIISConfiguration) - -from horizon import messages - -from django.http import HttpResponseRedirect - -LOG = logging.getLogger(__name__) - - -class Wizard(ModalFormMixin, SessionWizardView, generic.FormView): - template_name = 'services_tabs.html' - - def done(self, form_list, **kwargs): - link = self.request.__dict__['META']['HTTP_REFERER'] - environment_id = re.search('tabula/(\S+)', link).group(0)[7:-1] - - url = "/project/tabula/%s/" % environment_id - - service_type = form_list[0].data.get('0-service', '') - parameters = {'service_type': service_type} - data = form_list[1].data - if service_type == 'Active Directory': - parameters['configuration'] = 'standalone' - parameters['name'] = str(data.get('1-dc_name', 'noname')) - parameters['domain'] = parameters['name'] # Fix Me in orchestrator - parameters['adminPassword'] = str(data.get('1-adm_password', '')) - dc_count = int(data.get('1-dc_count', 1)) - recovery_password = str(data.get('1-recovery_password', '')) - parameters['units'] = [] - parameters['units'].append({'isMaster': True, - 'recoveryPassword': recovery_password, - 'location': 'west-dc'}) - for dc in range(dc_count - 1): - parameters['units'].append({ - 'isMaster': False, - 'recoveryPassword': recovery_password, - 'location': 'west-dc' - }) - - elif service_type == 'IIS': - password = data.get('1-adm_password', '') - parameters['name'] = str(data.get('1-iis_name', 'noname')) - parameters['credentials'] = {'username': 'Administrator', - 'password': password} - parameters['domain'] = str(data.get('1-iis_domain', '')) - password = form_list[1].data.get('1-adm_password', '') - domain = form_list[1].data.get('1-iis_domain', '') - dc_user = form_list[1].data.get('1-domain_user_name', '') - dc_pass = form_list[1].data.get('1-domain_user_password', '') - parameters['name'] = str(form_list[1].data.get('1-iis_name', - 'noname')) - parameters['domain'] = parameters['name'] - parameters['credentials'] = {'username': 'Administrator', - 'password': password} - parameters['domain'] = str(domain) - parameters['location'] = 'west-dc' - - parameters['units'] = [] - parameters['units'].append({'id': '1', - 'endpoint': [{'host': '10.0.0.1'}], - 'location': 'west-dc'}) - - service = api.service_create(self.request, environment_id, parameters) - - message = "The %s service successfully created." % service_type - messages.success(self.request, message) - return HttpResponseRedirect(url) - - def get_form(self, step=None, data=None, files=None): - - form = super(Wizard, self).get_form(step, data, files) - if data: - self.service_type = data.get('0-service', '') - if self.service_type == 'Active Directory': - self.form_list['1'] = WizardFormADConfiguration - elif self.service_type == 'IIS': - self.form_list['1'] = WizardFormIISConfiguration - - return form - - def get_form_kwargs(self, step=None): - return {'request': self.request} if step == u'1' else {} - - def get_form_step_data(self, form): - LOG.debug(form.data) - return form.data - - def get_context_data(self, form, **kwargs): - context = super(Wizard, self).get_context_data(form=form, **kwargs) - if self.steps.index > 0: - context.update({'service_type': self.service_type}) - return context - - -class IndexView(tables.DataTableView): - table_class = EnvironmentsTable - template_name = 'index.html' - - def get_data(self): - try: - environments = api.environments_list(self.request) - except: - environments = [] - exceptions.handle(self.request, - _('Unable to retrieve environments list.')) - return environments - - -class Services(tables.DataTableView): - table_class = ServicesTable - template_name = 'services.html' - - def get_context_data(self, **kwargs): - context = super(Services, self).get_context_data(**kwargs) - context['environment_name'] = self.environment_name - return context - - def get_data(self): - try: - self.environment_id = self.kwargs['environment_id'] - environment = api.environment_get(self.request, self.environment_id) - self.environment_name = environment.name - services = api.services_list(self.request, self.environment_id) - except: - services = [] - exceptions.handle(self.request, - _('Unable to retrieve list of services for ' - 'environment "%s".') % self.environment_name) - self._services = services - return self._services - - -class DetailServiceView(tabs.TabView): - tab_group_class = ServicesTabs - template_name = 'service_details.html' - - def get_context_data(self, **kwargs): - context = super(DetailServiceView, self).get_context_data(**kwargs) - context["service"] = self.get_data() - context["service_name"] = self.get_data().name - return context - - def get_data(self): - if not hasattr(self, "_service"): - try: - service_id = self.kwargs['service_id'] - service = api.get_service_datails(self.request, service_id) - except: - redirect = reverse('horizon:project:tabula:index') - exceptions.handle(self.request, - _('Unable to retrieve details for ' - 'service "%s".') % service_id, - redirect=redirect) - self._service = service - return self._service - - def get_tabs(self, request, *args, **kwargs): - service = self.get_data() - return self.tab_group_class(request, service=service, **kwargs) - - -class CreateEnvironmentView(workflows.WorkflowView): - workflow_class = CreateEnvironment - template_name = 'create_dc.html' - - def get_initial(self): - initial = super(CreateEnvironmentView, self).get_initial() - initial['project_id'] = self.request.user.tenant_id - initial['user_id'] = self.request.user.id - return initial diff --git a/dashboard/glazierdashboard/tabula/workflows.py b/dashboard/glazierdashboard/tabula/workflows.py deleted file mode 100644 index 44701dd6..00000000 --- a/dashboard/glazierdashboard/tabula/workflows.py +++ /dev/null @@ -1,96 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import json -import logging -import re - -from django.utils.text import normalize_newlines -from django.utils.translation import ugettext as _ - -from horizon import exceptions -from horizon import forms -from horizon import workflows - -from glazierdashboard.tabula import api - - -LOG = logging.getLogger(__name__) - - -class SelectProjectUserAction(workflows.Action): - project_id = forms.ChoiceField(label=_("Project")) - user_id = forms.ChoiceField(label=_("User")) - - def __init__(self, request, *args, **kwargs): - super(SelectProjectUserAction, self).__init__(request, *args, **kwargs) - # Set our project choices - projects = [(tenant.id, tenant.name) - for tenant in request.user.authorized_tenants] - self.fields['project_id'].choices = projects - - # Set our user options - users = [(request.user.id, request.user.username)] - self.fields['user_id'].choices = users - - class Meta: - name = _("Project & User") - # Unusable permission so this is always hidden. However, we - # keep this step in the workflow for validation/verification purposes. - permissions = ("!",) - - -class SelectProjectUser(workflows.Step): - action_class = SelectProjectUserAction - - -class ConfigureEnvironmentAction(workflows.Action): - name = forms.CharField(label=_("Environment Name"), required=True) - - class Meta: - name = _("Environment") - help_text_template = "_data_center_help.html" - - -class ConfigureEnvironment(workflows.Step): - action_class = ConfigureEnvironmentAction - contibutes = ('name',) - - def contribute(self, data, context): - if data: - context['name'] = data.get('name', '') - return context - - -class CreateEnvironment(workflows.Workflow): - slug = "create" - name = _("Create Environment") - finalize_button_name = _("Create") - success_message = _('Created environment "%s".') - failure_message = _('Unable to create environment "%s".') - success_url = "horizon:project:tabula:index" - default_steps = (SelectProjectUser, ConfigureEnvironment) - - def format_status_message(self, message): - name = self.context.get('name', 'noname') - return message % name - - def handle(self, request, context): - try: - api.environment_create(request, context) - return True - except: - exceptions.handle(request) - return False diff --git a/dashboard/glazierdashboard/templates/_data_center_help.html b/dashboard/glazierdashboard/templates/_data_center_help.html deleted file mode 100644 index 68ffe5a4..00000000 --- a/dashboard/glazierdashboard/templates/_data_center_help.html +++ /dev/null @@ -1,2 +0,0 @@ -{% load i18n %} -<p>{% blocktrans %}Data Center is an instance with different services.{% endblocktrans %}</p> \ No newline at end of file diff --git a/dashboard/glazierdashboard/templates/_dc_help.html b/dashboard/glazierdashboard/templates/_dc_help.html deleted file mode 100644 index 5e29e2d2..00000000 --- a/dashboard/glazierdashboard/templates/_dc_help.html +++ /dev/null @@ -1,3 +0,0 @@ -{% load i18n %} -<p>{% blocktrans %}You can deploy few Active Directory services with one domain name.{% endblocktrans %}</p> -<p>{% blocktrans %}The DNS service will automatically created for each Active Directory.{% endblocktrans %}</p> \ No newline at end of file diff --git a/dashboard/glazierdashboard/templates/_iis_help.html b/dashboard/glazierdashboard/templates/_iis_help.html deleted file mode 100644 index e8004c88..00000000 --- a/dashboard/glazierdashboard/templates/_iis_help.html +++ /dev/null @@ -1,2 +0,0 @@ -{% load i18n %} -<p>{% blocktrans %}You can deploy few Internet Information Services in one domain.{% endblocktrans %}</p> \ No newline at end of file diff --git a/dashboard/glazierdashboard/templates/_service_logs.html b/dashboard/glazierdashboard/templates/_service_logs.html deleted file mode 100644 index dda752a0..00000000 --- a/dashboard/glazierdashboard/templates/_service_logs.html +++ /dev/null @@ -1,7 +0,0 @@ -{% load i18n %} -<div class="clearfix"> - <h3 class="pull-left">{% trans "Service Logs" %}</h3> -</div> -<pre class="logs"> - {{ reports }} -</pre> \ No newline at end of file diff --git a/dashboard/glazierdashboard/templates/_services.html b/dashboard/glazierdashboard/templates/_services.html deleted file mode 100644 index ee5006f6..00000000 --- a/dashboard/glazierdashboard/templates/_services.html +++ /dev/null @@ -1,16 +0,0 @@ -{% load i18n %} - -<div class="status row-fluid detail"> - <h3>{% trans "Service Details" %}</h3> - <hr class="header_rule"> - <dl> - <dt>{% trans "Name" %}</dt> - <dd>{{ service_name }}</dd> - <dt>{% trans "Type" %}</dt> - <dd>{{ service_type }}</dd> - <dt>{% trans "Domain" %}</dt> - <dd>{{ service_domain }}</dd> - <dt>{% trans "Status" %}</dt> - <dd>{{ service_status }}</dd> - </dl> -</div> \ No newline at end of file diff --git a/dashboard/glazierdashboard/templates/_services_tabs.html b/dashboard/glazierdashboard/templates/_services_tabs.html deleted file mode 100644 index 3d0f583d..00000000 --- a/dashboard/glazierdashboard/templates/_services_tabs.html +++ /dev/null @@ -1,57 +0,0 @@ -{% extends "horizon/common/_modal_form.html" %} -{% load i18n horizon humanize %} - -{% block form_action %}{% url horizon:project:tabula:create %}?{{ request.POST.urlencode }}{% endblock %} - -{% block modal_id %}create_service{% endblock %} -{% block modal-header %}{% trans "Create Service" %}{% endblock %} - -{% block modal-body %} -<div class="left"> -<br> -{% if wizard.steps.next %} -<br><br><br> -{% endif %} -<table> -{{ wizard.management_form }} -{% if wizard.form.forms %} - {{ wizard.form.management_form }} - {% for form in wizard.form.forms %} - {{ form }} - {% endfor %} -{% else %} - {{ wizard.form }} -{% endif %} -{{ wizard.form.forms }} -</table> -</div> -<div class="right"> - {% if wizard.steps.prev %} - <H3>{{ service_type }} Service</H3> - {% if service_type == 'Active Directory' %} - <p>{% trans "Now you can set the parameters for Active Directory Service." %}</p> - <p>{% trans "You can create few Active Directory instances, in this case will be created one Main Active Directory server and few Secondary Active Directory servers." %}</p> - <p>{% trans "The DNS service will be automatically created on each Active Directory servers." %}</p> - {% else %} - <p>{% trans "Now you can set parameters for IIS Service." %}</p> - <p>{% trans "The IIS Service - it is the server with complex Internet Information Services infrastructure, which included to the domain infrasructure." %}</p> - <p>{% trans "Please, set the complex password for local administrator account." %}</p> - <p>{% trans "Also, you can add this IIS server to the existing domain and configure credentials for domain user." %}</p> - {% endif %} - - {% else %} - <h3>{% trans "Description" %}:</h3> - <p>{% trans "Now you can select the type of the service." %}</p> - <p>{% trans "The Active Directory Service allows to configure Domain Controllers with Active Directory and DNS infrastructure. You can create one Main Domain Controller and few Secondary Domain Controllers." %}</p> - <p>{% trans "The Internet Information Services allows to configure IIS servers, which can be included to the existing domain infrastructure." %}</p> - {% endif %} -</div> -{% endblock %} - -{% block modal-footer %} -{% if wizard.steps.prev %} -<input type="submit" class="btn btn-primary pull-right" value="{% trans 'Create' %}"/> -{% else %} -<button name="wizard_goto_step" class="btn btn-small" type="submit" value="{{ wizard.steps.next }}">{% trans "Next >" %}</button> -{% endif %} -{% endblock %} diff --git a/dashboard/glazierdashboard/templates/create.html b/dashboard/glazierdashboard/templates/create.html deleted file mode 100644 index 2dddf278..00000000 --- a/dashboard/glazierdashboard/templates/create.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends 'base.html' %} -{% load i18n %} -{% block title %}{% trans "Create Service" %}{% endblock %} - -{% block page_header %} - {% include "horizon/common/_page_header.html" with title=_("Create Service") %} -{% endblock page_header %} - -{% block main %} - {% include 'horizon/common/_workflow.html' %} -{% endblock %} diff --git a/dashboard/glazierdashboard/templates/create_dc.html b/dashboard/glazierdashboard/templates/create_dc.html deleted file mode 100644 index 2fc5894e..00000000 --- a/dashboard/glazierdashboard/templates/create_dc.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends 'base.html' %} -{% load i18n %} -{% block title %}{% trans "Create Windows Data Center" %}{% endblock %} - -{% block page_header %} - {% include "horizon/common/_page_header.html" with title=_("Create Windows Data Center") %} -{% endblock page_header %} - -{% block main %} - {% include 'horizon/common/_workflow.html' %} -{% endblock %} diff --git a/dashboard/glazierdashboard/templates/index.html b/dashboard/glazierdashboard/templates/index.html deleted file mode 100644 index 7c7147e4..00000000 --- a/dashboard/glazierdashboard/templates/index.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends 'base.html' %} -{% load i18n %} -{% block title %}{% trans "Environments" %}{% endblock %} - -{% block page_header %} - {% include "horizon/common/_page_header.html" with title=_("Environments") %} -{% endblock page_header %} - -{% block main %} - {{ table.render }} -{% endblock %} diff --git a/dashboard/glazierdashboard/templates/service_details.html b/dashboard/glazierdashboard/templates/service_details.html deleted file mode 100644 index bde27525..00000000 --- a/dashboard/glazierdashboard/templates/service_details.html +++ /dev/null @@ -1,15 +0,0 @@ -{% extends 'base.html' %} -{% load i18n sizeformat %} -{% block title %}{% trans "Service Detail" %}{% endblock %} - -{% block page_header %} - {% include "horizon/common/_page_header.html" with title="Service Detail: "|add:service.name %} -{% endblock page_header %} - -{% block main %} -<div class="row-fluid"> - <div class="span12"> - {{ tab_group.render }} - </div> -</div> -{% endblock %} diff --git a/dashboard/glazierdashboard/templates/services.html b/dashboard/glazierdashboard/templates/services.html deleted file mode 100644 index b009f6fa..00000000 --- a/dashboard/glazierdashboard/templates/services.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends 'base.html' %} -{% load i18n %} -{% block title %}{% trans "Environment Services" %}{% endblock %} - -{% block page_header %} - {% include "horizon/common/_page_header.html" with title="Environment "|add:environment_name %} -{% endblock page_header %} - -{% block main %} - {{ table.render }} -{% endblock %} diff --git a/dashboard/glazierdashboard/templates/update.html b/dashboard/glazierdashboard/templates/update.html deleted file mode 100644 index aba3dc9a..00000000 --- a/dashboard/glazierdashboard/templates/update.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends 'base.html' %} -{% load i18n %} -{% block title %}{% trans "Update Instance" %}{% endblock %} - -{% block page_header %} - {% include "horizon/common/_page_header.html" with title=_("Update Instance") %} -{% endblock page_header %} - -{% block main %} - {% include 'project/instances/_update.html' %} -{% endblock %} diff --git a/dashboard/glazierdashboard/test/__init__.py b/dashboard/glazierdashboard/test/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/dashboard/glazierdashboard/test/settings.py b/dashboard/glazierdashboard/test/settings.py deleted file mode 100644 index 501bc7f1..00000000 --- a/dashboard/glazierdashboard/test/settings.py +++ /dev/null @@ -1,70 +0,0 @@ -import socket - -from dashboard.settings import * - -socket.setdefaulttimeout(1) - -DEBUG = False -TEMPLATE_DEBUG = DEBUG - -SECRET_KEY = 'HELLA_SECRET!' - -DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3'}} - -TESTSERVER = 'http://testserver' - -INSTALLED_APPS += ('django_nose',) - -MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage' - -TEST_RUNNER = 'django_nose.NoseTestSuiteRunner' -NOSE_ARGS = ['--nocapture', - '--nologcapture', - '--cover-package=windc'] - -EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend' -SESSION_ENGINE = 'django.contrib.sessions.backends.cache' - -OPENSTACK_ADDRESS = "localhost" -OPENSTACK_ADMIN_TOKEN = "openstack" -OPENSTACK_KEYSTONE_URL = "http://%s:5000/v2.0" % OPENSTACK_ADDRESS -OPENSTACK_KEYSTONE_ADMIN_URL = "http://%s:35357/v2.0" % OPENSTACK_ADDRESS -OPENSTACK_KEYSTONE_DEFAULT_ROLE = "Member" - -# Silence logging output during tests. -LOGGING = { - 'version': 1, - 'disable_existing_loggers': False, - 'handlers': { - 'null': { - 'level': 'DEBUG', - 'class': 'django.utils.log.NullHandler', - }, - }, - 'loggers': { - 'django.db.backends': { - 'handlers': ['null'], - 'propagate': False, - }, - 'horizon': { - 'handlers': ['null'], - 'propagate': False, - }, - 'novaclient': { - 'handlers': ['null'], - 'propagate': False, - }, - 'keystoneclient': { - 'handlers': ['null'], - 'propagate': False, - }, - 'quantum': { - 'handlers': ['null'], - 'propagate': False, - }, - 'nose.plugins.manager': { - 'handlers': ['null'], - 'propagate': False, - } - } -} diff --git a/dashboard/glazierdashboard/version.py b/dashboard/glazierdashboard/version.py deleted file mode 100644 index ac241ae7..00000000 --- a/dashboard/glazierdashboard/version.py +++ /dev/null @@ -1,20 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -from tabula.openstack.common import version as common_version - -version_info = common_version.VersionInfo('tabula') diff --git a/dashboard/manage.py b/dashboard/manage.py deleted file mode 100755 index 00c53032..00000000 --- a/dashboard/manage.py +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env python - -import sys -import os - - -if __name__ == "__main__": - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "glazierdashboard.settings") - from django.core.management import execute_from_command_line - execute_from_command_line(sys.argv) diff --git a/dashboard/openstack-common.conf b/dashboard/openstack-common.conf deleted file mode 100644 index 507dc200..00000000 --- a/dashboard/openstack-common.conf +++ /dev/null @@ -1,7 +0,0 @@ -[DEFAULT] - -# The list of modules to copy from openstack-common -modules=setup,importutils,version - -# The base module to hold the copy of openstack.common -base=tabula diff --git a/dashboard/packages/python-portasclient-2013.1.a345.ga70b44e.tar.gz b/dashboard/packages/python-portasclient-2013.1.a345.ga70b44e.tar.gz deleted file mode 100644 index 92ff304b..00000000 Binary files a/dashboard/packages/python-portasclient-2013.1.a345.ga70b44e.tar.gz and /dev/null differ diff --git a/dashboard/run_tests.sh b/dashboard/run_tests.sh deleted file mode 100755 index 6dac0d35..00000000 --- a/dashboard/run_tests.sh +++ /dev/null @@ -1,442 +0,0 @@ -#!/bin/bash - -set -o errexit - -# ---------------UPDATE ME-------------------------------# -# Increment me any time the environment should be rebuilt. -# This includes dependncy changes, directory renames, etc. -# Simple integer secuence: 1, 2, 3... -environment_version=31 -#--------------------------------------------------------# - -function usage { - echo "Usage: $0 [OPTION]..." - echo "Run Horizon's test suite(s)" - echo "" - echo " -V, --virtual-env Always use virtualenv. Install automatically" - echo " if not present" - echo " -N, --no-virtual-env Don't use virtualenv. Run tests in local" - echo " environment" - echo " -c, --coverage Generate reports using Coverage" - echo " -f, --force Force a clean re-build of the virtual" - echo " environment. Useful when dependencies have" - echo " been added." - echo " -m, --manage Run a Django management command." - echo " --makemessages Update all translation files." - echo " --compilemessages Compile all translation files." - echo " -p, --pep8 Just run pep8" - echo " -t, --tabs Check for tab characters in files." - echo " -y, --pylint Just run pylint" - echo " -q, --quiet Run non-interactively. (Relatively) quiet." - echo " Implies -V if -N is not set." - echo " --only-selenium Run only the Selenium unit tests" - echo " --with-selenium Run unit tests including Selenium tests" - echo " --runserver Run the Django development server for" - echo " openstack_dashboard in the virtual" - echo " environment." - echo " --docs Just build the documentation" - echo " --backup-environment Make a backup of the environment on exit" - echo " --restore-environment Restore the environment before running" - echo " --destroy-environment DEstroy the environment and exit" - echo " -h, --help Print this usage message" - echo "" - echo "Note: with no options specified, the script will try to run the tests in" - echo " a virtual environment, If no virtualenv is found, the script will ask" - echo " if you would like to create one. If you prefer to run tests NOT in a" - echo " virtual environment, simply pass the -N option." - exit -} - -# DEFAULTS FOR RUN_TESTS.SH -# -root=`pwd` -venv=$root/.venv -with_venv=tools/with_venv.sh -included_dirs="openstack_dashboard horizon" - -always_venv=0 -backup_env=0 -command_wrapper="" -destroy=0 -force=0 -just_pep8=0 -just_pylint=0 -just_docs=0 -just_tabs=0 -never_venv=0 -quiet=0 -restore_env=0 -runserver=0 -only_selenium=0 -with_selenium=0 -testopts="" -testargs="" -with_coverage=0 -makemessages=0 -compilemessages=0 -manage=0 - -# Jenkins sets a "JOB_NAME" variable, if it's not set, we'll make it "default" -[ "$JOB_NAME" ] || JOB_NAME="default" - -function process_option { - case "$1" in - -h|--help) usage;; - -V|--virtual-env) always_venv=1; never_venv=0;; - -N|--no-virtual-env) always_venv=0; never_venv=1;; - -p|--pep8) just_pep8=1;; - -y|--pylint) just_pylint=1;; - -f|--force) force=1;; - -t|--tabs) just_tabs=1;; - -q|--quiet) quiet=1;; - -c|--coverage) with_coverage=1;; - -m|--manage) manage=1;; - --makemessages) makemessages=1;; - --compilemessages) compilemessages=1;; - --only-selenium) only_selenium=1;; - --with-selenium) with_selenium=1;; - --docs) just_docs=1;; - --runserver) runserver=1;; - --backup-environment) backup_env=1;; - --restore-environment) restore_env=1;; - --destroy-environment) destroy=1;; - -*) testopts="$testopts $1";; - *) testargs="$testargs $1" - esac -} - -function run_management_command { - ${command_wrapper} python $root/manage.py $testopts $testargs -} - -function run_server { - echo "Starting Django development server..." - ${command_wrapper} python $root/manage.py runserver $testopts $testargs - echo "Server stopped." -} - -function run_pylint { - echo "Running pylint ..." - PYTHONPATH=$root ${command_wrapper} pylint --rcfile=.pylintrc -f parseable $included_dirs > pylint.txt || true - CODE=$? - grep Global -A2 pylint.txt - if [ $CODE -lt 32 ]; then - echo "Completed successfully." - exit 0 - else - echo "Completed with problems." - exit $CODE - fi -} - -function run_pep8 { - echo "Running pep8 ..." - ${command_wrapper} pep8 $included_dirs -} - -function run_sphinx { - echo "Building sphinx..." - export DJANGO_SETTINGS_MODULE=openstack_dashboard.settings - ${command_wrapper} sphinx-build -b html doc/source doc/build/html - echo "Build complete." -} - -function tab_check { - TAB_VIOLATIONS=`find $included_dirs -type f -regex ".*\.\(css\|js\|py\|html\)" -print0 | xargs -0 awk '/\t/' | wc -l` - if [ $TAB_VIOLATIONS -gt 0 ]; then - echo "TABS! $TAB_VIOLATIONS of them! Oh no!" - HORIZON_FILES=`find $included_dirs -type f -regex ".*\.\(css\|js\|py|\html\)"` - for TABBED_FILE in $HORIZON_FILES - do - TAB_COUNT=`awk '/\t/' $TABBED_FILE | wc -l` - if [ $TAB_COUNT -gt 0 ]; then - echo "$TABBED_FILE: $TAB_COUNT" - fi - done - fi - return $TAB_VIOLATIONS; -} - -function destroy_venv { - echo "Cleaning environment..." - echo "Removing virtualenv..." - rm -rf $venv - echo "Virtualenv removed." - rm -f .environment_version - echo "Environment cleaned." -} - -function environment_check { - echo "Checking environment." - if [ -f .environment_version ]; then - ENV_VERS=`cat .environment_version` - if [ $ENV_VERS -eq $environment_version ]; then - if [ -e ${venv} ]; then - # If the environment exists and is up-to-date then set our variables - command_wrapper="${root}/${with_venv}" - echo "Environment is up to date." - return 0 - fi - fi - fi - - if [ $always_venv -eq 1 ]; then - install_venv - else - if [ ! -e ${venv} ]; then - echo -e "Environment not found. Install? (Y/n) \c" - else - echo -e "Your environment appears to be out of date. Update? (Y/n) \c" - fi - read update_env - if [ "x$update_env" = "xY" -o "x$update_env" = "x" -o "x$update_env" = "xy" ]; then - install_venv - else - # Set our command wrapper anyway. - command_wrapper="${root}/${with_venv}" - fi - fi -} - -function sanity_check { - # Anything that should be determined prior to running the tests, server, etc. - # Don't sanity-check anything environment-related in -N flag is set - if [ $never_venv -eq 0 ]; then - if [ ! -e ${venv} ]; then - echo "Virtualenv not found at $venv. Did install_venv.py succeed?" - exit 1 - fi - fi - # Remove .pyc files. This is sanity checking because they can linger - # after old files are deleted. - find . -name "*.pyc" -exec rm -rf {} \; -} - -function backup_environment { - if [ $backup_env -eq 1 ]; then - echo "Backing up environment \"$JOB_NAME\"..." - if [ ! -e ${venv} ]; then - echo "Environment not installed. Cannot back up." - return 0 - fi - if [ -d /tmp/.horizon_environment/$JOB_NAME ]; then - mv /tmp/.horizon_environment/$JOB_NAME /tmp/.horizon_environment/$JOB_NAME.old - rm -rf /tmp/.horizon_environment/$JOB_NAME - fi - mkdir -p /tmp/.horizon_environment/$JOB_NAME - cp -r $venv /tmp/.horizon_environment/$JOB_NAME/ - cp .environment_version /tmp/.horizon_environment/$JOB_NAME/ - # Remove the backup now that we've completed successfully - rm -rf /tmp/.horizon_environment/$JOB_NAME.old - echo "Backup completed" - fi -} - -function restore_environment { - if [ $restore_env -eq 1 ]; then - echo "Restoring environment from backup..." - if [ ! -d /tmp/.horizon_environment/$JOB_NAME ]; then - echo "No backup to restore from." - return 0 - fi - - cp -r /tmp/.horizon_environment/$JOB_NAME/.venv ./ || true - cp -r /tmp/.horizon_environment/$JOB_NAME/.environment_version ./ || true - - echo "Environment restored successfully." - fi -} - -function install_venv { - # Install with install_venv.py - export PIP_DOWNLOAD_CACHE=${PIP_DOWNLOAD_CACHE-/tmp/.pip_download_cache} - export PIP_USE_MIRRORS=true - if [ $quiet -eq 1 ]; then - export PIP_NO_INPUT=true - fi - echo "Fetching new src packages..." - rm -rf $venv/src - python tools/install_venv.py - command_wrapper="$root/${with_venv}" - # Make sure it worked and record the environment version - sanity_check - chmod -R 754 $venv - echo $environment_version > .environment_version -} - -function run_tests { - sanity_check - - if [ $with_selenium -eq 1 ]; then - export WITH_SELENIUM=1 - elif [ $only_selenium -eq 1 ]; then - export WITH_SELENIUM=1 - export SKIP_UNITTESTS=1 - fi - - if [ -z "$testargs" ]; then - run_tests_all - else - run_tests_subset - fi -} - -function run_tests_subset { - project=`echo $testargs | awk -F. '{print $1}'` - ${command_wrapper} python $root/manage.py test --settings=$project.test.settings $testopts $testargs -} - -function run_tests_all { - echo "Running Horizon application tests" - export NOSE_XUNIT_FILE=horizon/nosetests.xml - if [ "$NOSE_WITH_HTML_OUTPUT" = '1' ]; then - export NOSE_HTML_OUT_FILE='horizon_nose_results.html' - fi - ${command_wrapper} coverage erase - ${command_wrapper} coverage run -p $root/manage.py test horizon --settings=horizon.test.settings $testopts - # get results of the Horizon tests - HORIZON_RESULT=$? - - echo "Running openstack_dashboard tests" - export NOSE_XUNIT_FILE=openstack_dashboard/nosetests.xml - if [ "$NOSE_WITH_HTML_OUTPUT" = '1' ]; then - export NOSE_HTML_OUT_FILE='dashboard_nose_results.html' - fi - ${command_wrapper} coverage run -p $root/manage.py test openstack_dashboard --settings=openstack_dashboard.test.settings $testopts - # get results of the openstack_dashboard tests - DASHBOARD_RESULT=$? - - if [ $with_coverage -eq 1 ]; then - echo "Generating coverage reports" - ${command_wrapper} coverage combine - ${command_wrapper} coverage xml -i --omit='/usr*,setup.py,*egg*,.venv/*' - ${command_wrapper} coverage html -i --omit='/usr*,setup.py,*egg*,.venv/*' -d reports - fi - # Remove the leftover coverage files from the -p flag earlier. - rm -f .coverage.* - - if [ $(($HORIZON_RESULT || $DASHBOARD_RESULT)) -eq 0 ]; then - echo "Tests completed successfully." - else - echo "Tests failed." - fi - exit $(($HORIZON_RESULT || $DASHBOARD_RESULT)) -} - -function run_makemessages { - cd horizon - ${command_wrapper} $root/manage.py makemessages --all --no-obsolete - HORIZON_PY_RESULT=$? - ${command_wrapper} $root/manage.py makemessages -d djangojs --all --no-obsolete - HORIZON_JS_RESULT=$? - cd ../openstack_dashboard - ${command_wrapper} $root/manage.py makemessages --all --no-obsolete - DASHBOARD_RESULT=$? - cd .. - exit $(($HORIZON_PY_RESULT || $HORIZON_JS_RESULT || $DASHBOARD_RESULT)) -} - -function run_compilemessages { - cd horizon - ${command_wrapper} $root/manage.py compilemessages - HORIZON_PY_RESULT=$? - cd ../openstack_dashboard - ${command_wrapper} $root/manage.py compilemessages - DASHBOARD_RESULT=$? - cd .. - exit $(($HORIZON_PY_RESULT || $DASHBOARD_RESULT)) -} - - -# ---------PREPARE THE ENVIRONMENT------------ # - -# PROCESS ARGUMENTS, OVERRIDE DEFAULTS -for arg in "$@"; do - process_option $arg -done - -if [ $quiet -eq 1 ] && [ $never_venv -eq 0 ] && [ $always_venv -eq 0 ] -then - always_venv=1 -fi - -# If destroy is set, just blow it away and exit. -if [ $destroy -eq 1 ]; then - destroy_venv - exit 0 -fi - -# Ignore all of this if the -N flag was set -if [ $never_venv -eq 0 ]; then - - # Restore previous environment if desired - if [ $restore_env -eq 1 ]; then - restore_environment - fi - - # Remove the virtual environment if --force used - if [ $force -eq 1 ]; then - destroy_venv - fi - - # Then check if it's up-to-date - environment_check - - # Create a backup of the up-to-date environment if desired - if [ $backup_env -eq 1 ]; then - backup_environment - fi -fi - -# ---------EXERCISE THE CODE------------ # - -# Run management commands -if [ $manage -eq 1 ]; then - run_management_command - exit $? -fi - -# Build the docs -if [ $just_docs -eq 1 ]; then - run_sphinx - exit $? -fi - -# Update translation files -if [ $makemessages -eq 1 ]; then - run_makemessages - exit $? -fi - -# Compile translation files -if [ $compilemessages -eq 1 ]; then - run_compilemessages - exit $? -fi - -# PEP8 -if [ $just_pep8 -eq 1 ]; then - run_pep8 - exit $? -fi - -# Pylint -if [ $just_pylint -eq 1 ]; then - run_pylint - exit $? -fi - -# Tab checker -if [ $just_tabs -eq 1 ]; then - tab_check - exit $? -fi - -# Django development server -if [ $runserver -eq 1 ]; then - run_server - exit $? -fi - -# Full test suite -run_tests || exit diff --git a/dashboard/setup.cfg b/dashboard/setup.cfg deleted file mode 100644 index 79034b3c..00000000 --- a/dashboard/setup.cfg +++ /dev/null @@ -1,9 +0,0 @@ -[build_sphinx] -all_files = 1 -build-dir = doc/build -source-dir = doc/source - -[nosetests] -verbosity=2 -detailed-errors=1 - diff --git a/dashboard/setup.py b/dashboard/setup.py deleted file mode 100755 index 4f73e961..00000000 --- a/dashboard/setup.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import setuptools - -from glazierdashboard.openstack.common import setup - -requires = setup.parse_requirements() -depend_links = setup.parse_dependency_links() -project = 'tabula' - -setuptools.setup( - name=project, - version=setup.get_version(project, '2013.1'), - description="The OpenStack Dashboard.", - license='Apache 2.0', - author='OpenStack', - author_email='horizon@lists.launchpad.net', - url='https://github.com/openstack/horizon/', - packages=setuptools.find_packages(exclude=['bin']), - cmdclass=setup.get_cmdclass(), - include_package_data=True, - install_requires=requires, - dependency_links=depend_links, - classifiers=['Development Status :: 5 - Production/Stable', - 'Framework :: Django', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: Apache Software License', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Topic :: Internet :: WWW/HTTP', - 'Environment :: OpenStack'] -) diff --git a/dashboard/tools/install_venv.py b/dashboard/tools/install_venv.py deleted file mode 100644 index 2aa61068..00000000 --- a/dashboard/tools/install_venv.py +++ /dev/null @@ -1,69 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Copyright 2010 OpenStack LLC. -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os -import subprocess -import sys - -import install_venv_common as install_venv - - -def print_help(): - help = """ - Tabula development environment setup is complete. - - Tabula development uses virtualenv to track and manage Python dependencies - while in development and testing. - - To activate the Tabula virtualenv for the extent of your current shell session - you can run: - - $ source .venv/bin/activate - - Or, if you prefer, you can run commands in the virtualenv on a case by case - basis by running: - - $ tools/with_venv.sh <your command> - - Also, make test will automatically use the virtualenv. - """ - print help - - -def main(argv): - root = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) - venv = os.path.join(root, '.venv') - pip_requires = os.path.join(root, 'tools', 'pip-requires') - test_requires = os.path.join(root, 'tools', 'test-requires') - py_version = "python%s.%s" % (sys.version_info[0], sys.version_info[1]) - project = 'tabula' - install = install_venv.InstallVenv(root, venv, pip_requires, test_requires, - py_version, project) - options = install.parse_args(argv) - install.check_python_version() - install.check_dependencies() - install.create_virtualenv(no_site_packages=options.no_site_packages) - install.install_dependencies() - install.post_process() - print_help() - -if __name__ == '__main__': - main(sys.argv) diff --git a/dashboard/tools/install_venv_common.py b/dashboard/tools/install_venv_common.py deleted file mode 100644 index 1ea3b2df..00000000 --- a/dashboard/tools/install_venv_common.py +++ /dev/null @@ -1,219 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2013 OpenStack, LLC -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides methods needed by installation script for OpenStack development -virtual environments. - -Synced in from openstack-common -""" - -import argparse -import os -import subprocess -import sys - - -class InstallVenv(object): - - def __init__(self, root, venv, pip_requires, test_requires, py_version, - project): - self.root = root - self.venv = venv - self.pip_requires = pip_requires - self.test_requires = test_requires - self.py_version = py_version - self.project = project - - def die(self, message, *args): - print >> sys.stderr, message % args - sys.exit(1) - - def check_python_version(self): - if sys.version_info < (2, 6): - self.die("Need Python Version >= 2.6") - - def run_command_with_code(self, cmd, redirect_output=True, - check_exit_code=True): - """Runs a command in an out-of-process shell. - - Returns the output of that command. Working directory is self.root. - """ - if redirect_output: - stdout = subprocess.PIPE - else: - stdout = None - - proc = subprocess.Popen(cmd, cwd=self.root, stdout=stdout) - output = proc.communicate()[0] - if check_exit_code and proc.returncode != 0: - self.die('Command "%s" failed.\n%s', ' '.join(cmd), output) - return (output, proc.returncode) - - def run_command(self, cmd, redirect_output=True, check_exit_code=True): - return self.run_command_with_code(cmd, redirect_output, - check_exit_code)[0] - - def get_distro(self): - if (os.path.exists('/etc/fedora-release') or - os.path.exists('/etc/redhat-release')): - return Fedora(self.root, self.venv, self.pip_requires, - self.test_requires, self.py_version, self.project) - else: - return Distro(self.root, self.venv, self.pip_requires, - self.test_requires, self.py_version, self.project) - - def check_dependencies(self): - self.get_distro().install_virtualenv() - - def create_virtualenv(self, no_site_packages=True): - """Creates the virtual environment and installs PIP. - - Creates the virtual environment and installs PIP only into the - virtual environment. - """ - if not os.path.isdir(self.venv): - print 'Creating venv...', - if no_site_packages: - self.run_command(['virtualenv', '-q', '--no-site-packages', - self.venv]) - else: - self.run_command(['virtualenv', '-q', self.venv]) - print 'done.' - print 'Installing pip in venv...', - if not self.run_command(['tools/with_venv.sh', 'easy_install', - 'pip>1.0']).strip(): - self.die("Failed to install pip.") - print 'done.' - else: - print "venv already exists..." - pass - - def pip_install(self, *args): - self.run_command(['tools/with_venv.sh', - 'pip', 'install', '--upgrade'] + list(args), - redirect_output=False) - - def install_dependencies(self): - print 'Installing dependencies with pip (this can take a while)...' - - # First things first, make sure our venv has the latest pip and - # distribute. - # NOTE: we keep pip at version 1.1 since the most recent version causes - # the .venv creation to fail. See: - # https://bugs.launchpad.net/nova/+bug/1047120 - self.pip_install('pip==1.1') - self.pip_install('distribute') - - # Install greenlet by hand - just listing it in the requires file does - # not - # get it installed in the right order - self.pip_install('greenlet') - - self.pip_install('-r', self.test_requires) - self.pip_install('-r', self.pip_requires) - - def post_process(self): - self.get_distro().post_process() - - def parse_args(self, argv): - """Parses command-line arguments.""" - parser = argparse.ArgumentParser() - parser.add_argument('-n', '--no-site-packages', - action='store_true', - help="Do not inherit packages from global Python " - "install") - return parser.parse_args(argv[1:]) - - -class Distro(InstallVenv): - - def check_cmd(self, cmd): - return bool(self.run_command(['which', cmd], - check_exit_code=False).strip()) - - def install_virtualenv(self): - if self.check_cmd('virtualenv'): - return - - if self.check_cmd('easy_install'): - print 'Installing virtualenv via easy_install...', - if self.run_command(['easy_install', 'virtualenv']): - print 'Succeeded' - return - else: - print 'Failed' - - self.die('ERROR: virtualenv not found.\n\n%s development' - ' requires virtualenv, please install it using your' - ' favorite package management tool' % self.project) - - def post_process(self): - """Any distribution-specific post-processing gets done here. - - In particular, this is useful for applying patches to code inside - the venv. - """ - pass - - -class Fedora(Distro): - """This covers all Fedora-based distributions. - - Includes: Fedora, RHEL, CentOS, Scientific Linux - """ - - def check_pkg(self, pkg): - return self.run_command_with_code(['rpm', '-q', pkg], - check_exit_code=False)[1] == 0 - - def yum_install(self, pkg, **kwargs): - print "Attempting to install '%s' via yum" % pkg - self.run_command(['sudo', 'yum', 'install', '-y', pkg], **kwargs) - - def apply_patch(self, originalfile, patchfile): - self.run_command(['patch', originalfile, patchfile]) - - def install_virtualenv(self): - if self.check_cmd('virtualenv'): - return - - if not self.check_pkg('python-virtualenv'): - self.yum_install('python-virtualenv', check_exit_code=False) - - super(Fedora, self).install_virtualenv() - - def post_process(self): - """Workaround for a bug in eventlet. - - This currently affects RHEL6.1, but the fix can safely be - applied to all RHEL and Fedora distributions. - - This can be removed when the fix is applied upstream. - - Nova: https://bugs.launchpad.net/nova/+bug/884915 - Upstream: https://bitbucket.org/which_linden/eventlet/issue/89 - """ - - # Install "patch" program if it's not there - if not self.check_pkg('patch'): - self.yum_install('patch') - - # Apply the eventlet patch - self.apply_patch(os.path.join(self.venv, 'lib', self.py_version, - 'site-packages', - 'eventlet/green/subprocess.py'), - 'contrib/redhat-eventlet.patch') diff --git a/dashboard/tools/pip-requires b/dashboard/tools/pip-requires deleted file mode 100644 index bba8dd72..00000000 --- a/dashboard/tools/pip-requires +++ /dev/null @@ -1,6 +0,0 @@ -# Core Requirements -Django>=1.4,<1.5 -anyjson -#Fix for bug https://bugs.launchpad.net/python-keystoneclient/+bug/1116740 -backports.ssl_match_hostname -requests==0.14.2 \ No newline at end of file diff --git a/dashboard/tools/rfc.sh b/dashboard/tools/rfc.sh deleted file mode 100755 index 15781e52..00000000 --- a/dashboard/tools/rfc.sh +++ /dev/null @@ -1,145 +0,0 @@ -#!/bin/sh -e -# Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com> -# This initial version of this file was taken from the source tree -# of GlusterFS. It was not directly attributed, but is assumed to be -# Copyright (c) 2010-2011 Gluster, Inc and release GPLv3 -# Subsequent modifications are Copyright (c) 2012 OpenStack, LLC. -# -# GlusterFS 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 3 of the License, -# or (at your option) any later version. -# -# GlusterFS 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 this program. If not, see -# <http://www.gnu.org/licenses/>. - - -branch="master"; - -set_hooks_commit_msg() -{ - top_dir=`git rev-parse --show-toplevel` - f="${top_dir}/.git/hooks/commit-msg"; - u="https://review.openstack.org/tools/hooks/commit-msg"; - - if [ -x "$f" ]; then - return; - fi - - curl -o $f $u || wget -O $f $u; - - chmod +x $f; - - GIT_EDITOR=true git commit --amend -} - -add_remote() -{ - username=$1 - project=$2 - - echo "No remote set, testing ssh://$username@review.openstack.org:29418" - if project_list=`ssh -p29418 -o StrictHostKeyChecking=no $username@review.openstack.org gerrit ls-projects 2>/dev/null` - then - echo "$username@review.openstack.org:29418 worked." - if echo $project_list | grep $project >/dev/null - then - echo "Creating a git remote called gerrit that maps to:" - echo " ssh://$username@review.openstack.org:29418/$project" - git remote add gerrit ssh://$username@review.openstack.org:29418/$project - else - echo "The current project name, $project, is not a known project." - echo "Please either reclone from github/gerrit or create a" - echo "remote named gerrit that points to the intended project." - return 1 - fi - - return 0 - fi - return 1 -} - -check_remote() -{ - if ! git remote | grep gerrit >/dev/null 2>&1 - then - origin_project=`git remote show origin | grep 'Fetch URL' | perl -nle '@fields = split(m|[:/]|); $len = $#fields; print $fields[$len-1], "/", $fields[$len];'` - if add_remote $USERNAME $origin_project - then - return 0 - else - echo "Your local name doesn't work on Gerrit." - echo -n "Enter Gerrit username (same as launchpad): " - read gerrit_user - if add_remote $gerrit_user $origin_project - then - return 0 - else - echo "Can't infer where gerrit is - please set a remote named" - echo "gerrit manually and then try again." - echo - echo "For more information, please see:" - echo "\thttp://wiki.openstack.org/GerritWorkflow" - exit 1 - fi - fi - fi -} - -rebase_changes() -{ - git fetch; - - GIT_EDITOR=true git rebase -i origin/$branch || exit $?; -} - - -assert_diverge() -{ - if ! git diff origin/$branch..HEAD | grep -q . - then - echo "No changes between the current branch and origin/$branch." - exit 1 - fi -} - - -main() -{ - set_hooks_commit_msg; - - check_remote; - - rebase_changes; - - assert_diverge; - - bug=$(git show --format='%s %b' | perl -nle 'if (/\b([Bb]ug|[Ll][Pp])\s*[#:]?\s*(\d+)/) {print "$2"; exit}') - - bp=$(git show --format='%s %b' | perl -nle 'if (/\b([Bb]lue[Pp]rint|[Bb][Pp])\s*[#:]?\s*([0-9a-zA-Z-_]+)/) {print "$2"; exit}') - - if [ "$DRY_RUN" = 1 ]; then - drier='echo -e Please use the following command to send your commits to review:\n\n' - else - drier= - fi - - local_branch=`git branch | grep -Ei "\* (.*)" | cut -f2 -d' '` - if [ -z "$bug" ]; then - if [ -z "$bp" ]; then - $drier git push gerrit HEAD:refs/for/$branch/$local_branch; - else - $drier git push gerrit HEAD:refs/for/$branch/bp/$bp; - fi - else - $drier git push gerrit HEAD:refs/for/$branch/bug/$bug; - fi -} - -main "$@" diff --git a/dashboard/tools/test-requires b/dashboard/tools/test-requires deleted file mode 100644 index c1da7cae..00000000 --- a/dashboard/tools/test-requires +++ /dev/null @@ -1,18 +0,0 @@ -distribute>=0.6.24 - -# Testing Requirements -coverage -django-nose -mox -nose -nose-exclude -nosexcover -openstack.nose_plugin -nosehtmloutput -pep8>=1.3 -pylint -selenium - -# Docs Requirements -sphinx -docutils==0.9.1 # for bug 1091333, remove after sphinx >1.1.3 is released. diff --git a/dashboard/tools/with_venv.sh b/dashboard/tools/with_venv.sh deleted file mode 100755 index c8d2940f..00000000 --- a/dashboard/tools/with_venv.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -TOOLS=`dirname $0` -VENV=$TOOLS/../.venv -source $VENV/bin/activate && $@ diff --git a/docs/.gitignore b/docs/.gitignore deleted file mode 100644 index c4c2ae4b..00000000 --- a/docs/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -#IntelJ Idea -.idea/ - -#Build results -target - -#Translation build -*.mo -*.pot diff --git a/docs/LICENSE b/docs/LICENSE deleted file mode 100644 index 68c771a0..00000000 --- a/docs/LICENSE +++ /dev/null @@ -1,176 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - diff --git a/docs/README.rst b/docs/README.rst deleted file mode 100644 index 3725a9fd..00000000 --- a/docs/README.rst +++ /dev/null @@ -1,47 +0,0 @@ -Glazier Manuals -+++++++++++++++++ - -This repository contains documentation for the -Glazier project. It includes: - - * API Specification - * Architecture - -For more details, see the `Glazier <http://glazier.mirantis.com>`_. - -Prerequisites -============= -`Apache Maven <http://maven.apache.org/>`_ must be installed to build the -documentation. - -To install Maven 3 for Ubuntu 12.04 and later,and Debian wheezy and later:: - - apt-get install maven - -On Fedora 15 and later:: - - yum install maven3 - -Building -======== -The different manuals are in subdirectories of the -``docs/src/`` directory. - -To build a specific guide, look for a ``pom.xml`` file within a subdirectory, -then run the ``mvn`` command in that directory. For example:: - - cd docs/src/glazier-manual - mvn clean generate-sources - -The generated PDF documentation file is:: - - docs/src/glazier-manual/src/target/docbkx/pdf/glazier-manual.pdf - -The root of the generated HTML documentation is:: - - docs/src/glazier-manual/src/target/docbkx/webhelp/glazier-manual/content/index.html - -Installing -========== -Refer to http://glazier.openstack.org to see where these documents are published -and to learn more about the Glazier project. diff --git a/docs/src/glazier-manual/pom.xml b/docs/src/glazier-manual/pom.xml deleted file mode 100644 index 5bc6ada6..00000000 --- a/docs/src/glazier-manual/pom.xml +++ /dev/null @@ -1,54 +0,0 @@ -<!-- - Copyright (c) 2013 Mirantis, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> - <modelVersion>4.0.0</modelVersion> - <groupId>com.mirantis.glazier</groupId> - <artifactId>manuals</artifactId> - <version>1.0.0-SNAPSHOT</version> - <packaging>jar</packaging> - <name>Glazier Project Documentation</name> - <build> - <plugins> - <plugin> - <groupId>com.agilejava.docbkx</groupId> - <artifactId>docbkx-maven-plugin</artifactId> - <executions> - <execution> - <goals> - <goal>generate-pdf</goal> - <goal>generate-webhelp</goal> - </goals> - <phase>generate-sources</phase> - </execution> - </executions> - <configuration> - <xincludeSupported>true</xincludeSupported> - <chunkSectionDepth>100</chunkSectionDepth> - <postProcess> - <copy todir="target/docbkx/webhelp/glazier-manual/content/figures"> - <fileset dir="src/docbkx/figures"> - <include name="**/*.png"/> - </fileset> - </copy> - </postProcess> - </configuration> - </plugin> - </plugins> - </build> -</project> diff --git a/docs/src/glazier-manual/src/docbkx/figures/api_workflow.png b/docs/src/glazier-manual/src/docbkx/figures/api_workflow.png deleted file mode 100755 index e1e19f82..00000000 Binary files a/docs/src/glazier-manual/src/docbkx/figures/api_workflow.png and /dev/null differ diff --git a/docs/src/glazier-manual/src/docbkx/figures/architecture_diagram.png b/docs/src/glazier-manual/src/docbkx/figures/architecture_diagram.png deleted file mode 100755 index cf374dd0..00000000 Binary files a/docs/src/glazier-manual/src/docbkx/figures/architecture_diagram.png and /dev/null differ diff --git a/docs/src/glazier-manual/src/docbkx/glazier-manual.xml b/docs/src/glazier-manual/src/docbkx/glazier-manual.xml deleted file mode 100644 index 042a2572..00000000 --- a/docs/src/glazier-manual/src/docbkx/glazier-manual.xml +++ /dev/null @@ -1,1910 +0,0 @@ -<!-- - Copyright (c) 2013 Mirantis, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<book xmlns="http://docbook.org/ns/docbook" - xmlns:xlink="http://www.w3.org/1999/xlink" - xmlns:xi="http://www.w3.org/2001/XInclude" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns:m="http://www.w3.org/1998/Math/MathML" - xmlns:html="http://www.w3.org/1999/xhtml" version="5.0" status="DRAFT" - xsi:schemaLocation="http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd - http://www.w3.org/1999/xlink http://www.w3.org/1999/xlink.xsd -http://docbook.org/ns/docbook " xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> - <title>Glazier Project Documentation</title> - <info> - <author> - <personname> - <firstname/> - <surname/> - </personname> - <affiliation> - <orgname>Mirantis, Inc.</orgname> - </affiliation> - </author> - <copyright> - <year>2013</year> - <holder>Mirantis, Inc.</holder> - </copyright> - <releaseinfo>v0.1</releaseinfo> - <productname>Glazier™</productname> - <pubdate>2013-04-04</pubdate> - <legalnotice role="apache2"> - <annotation> - <remark>Copyright details are filled in by the template. Change - the value of the role - attribute on the legalnotice element to change the license. - </remark> - </annotation> - </legalnotice> - <abstract> - <para>This document is intended for individuals who wish to - configure - and use our product or intend to contribute. - </para> - </abstract> - <cover> - <para>this is a placeholder for the front cover</para> - </cover> - <cover> - <para>this is a placeholder for the back cover</para> - </cover> - </info> - <chapter> - <title>Overview</title> - <para>Welcome to Glazier Project. - </para> - <section> - <title>Intended Audience</title> - <para>This guide is intended to individuals who want to contribute - to our - project. - </para> - </section> - <section> - <title>Document Change History</title> - <para>This version of the Glazier Manual replaces and obsoletes all - previous versions. The - most recent changes are described in the table below: - </para> - <informaltable rules="all"> - <thead> - <tr> - <td align="center" colspan="1">Revision Date</td> - <td align="center" colspan="4">Summary of Changes</td> - </tr> - </thead> - <tbody> - <tr> - <td colspan="1" align="center">April. 4, 2013</td> - <td colspan="4"> - <itemizedlist spacing="compact"> - <listitem> - <para>Initial document creation.</para> - </listitem> - </itemizedlist> - </td> - </tr> - </tbody> - </informaltable> - </section> - <section> - <title>Additional Resources</title> - <itemizedlist spacing="compact"> - <listitem> - <para> - <link xlink:href="http://www.mirantis.com"> - Mirantis - Cloud Software - </link> - </para> - </listitem> - </itemizedlist> - </section> - </chapter> - <chapter id="architecture"> - <title>Architecture</title> - <figure xml:id="glazierarchitecture"> - <title>Architecture</title> - <mediaobject> - <imageobject role="fo"> - <imagedata fileref="figures/architecture_diagram.png" - contentwidth="5in"/> - </imageobject> - <imageobject role="html"> - <imagedata fileref="figures/architecture_diagram.png"/> - </imageobject> - </mediaobject> - </figure> - <para> - The Glazier architecture has the following components: - <itemizedlist spacing="compact"> - <listitem> - <para>Glazier Dashboard - UI for the Glazier, extends - Horizon - </para> - </listitem> - <listitem> - <para>REST API - exposes Glazier API via REST. Maintains - environment configurations in Database - </para> - </listitem> - <listitem> - <para>Glazier Python Client - Python client for Glazier - REST API - </para> - </listitem> - <listitem> - <para>Orchestration Engine - builds the environment as - configured by the user. - Turns environment configurations into a Heat templates - for VM provision and Glazier Agent commands for service - deployment - </para> - </listitem> - <listitem> - <para>Glazier Agent - built into Windows Server VM images. - Executes commands sent by Orchestration Engine - </para> - </listitem> - </itemizedlist> - </para> - </chapter> - <chapter> - <title>API Specification</title> - <informaltable rules="all"> - <thead> - <tr> - <td align="center" colspan="1">Revision Date</td> - <td align="center" colspan="4">Summary of Changes</td> - </tr> - </thead> - <tbody> - <tr> - <td colspan="1" align="center">February 4, 2013</td> - <td colspan="4"> - <itemizedlist spacing="compact"> - <listitem> - <para>Initial document creation</para> - </listitem> - </itemizedlist> - </td> - </tr> - <tr> - <td colspan="1" align="center">February 22, 2013</td> - <td colspan="4"> - <itemizedlist spacing="compact"> - <listitem> - <para>Enhance API with latest architecture - changes - </para> - </listitem> - </itemizedlist> - </td> - </tr> - <tr> - <td colspan="1" align="center">March 06, 2013</td> - <td colspan="4"> - <itemizedlist spacing="compact"> - <listitem> - <para>Fix specification according to remarks - from Dmitry Teselkin - </para> - </listitem> - </itemizedlist> - </td> - </tr> - </tbody> - </informaltable> - <section> - <title>Introduction</title> - <para>Glazier Service API is a programmatic interface used for interaction - with Glazier. Other interaction - mechanisms like Glazier Dashboard or Glazier CLI should use API as underlying - protocol for interaction. - </para> - - <glossary> - <para>For detailed information about entities and terms used in this document, please refer first to - <xref - linkend="architecture"/>. - </para> - <glossentry> - <glossterm>Environment</glossterm> - <glossdef> - <para>Environment is a set of logically related Services managed by a single tenant. Environment - defines Windows environment boundaries. - </para> - <para>Services within single Environment may comprise some complex configuration while Services - in different Environments are always independent from one another. Each Environment is - associated with single OpenStack project (tenant). - </para> - </glossdef> - </glossentry> - <glossentry> - <glossterm>Service</glossterm> - <glossdef> - <para>Service is building block of Windows environment. Service is a set of one or more Virtual - Machines sharing a common purpose and configured together. Each service belongs to a single - Environment and single Service Type. - </para> - <para>Services are comprised from one or more Service Units.</para> - </glossdef> - </glossentry> - <glossentry> - <glossterm>Service Type</glossterm> - <glossdef> - <para>Service type is definition for describing set of features exposed by service.</para> - </glossdef> - </glossentry> - <glossentry> - <glossterm>Service Unit</glossterm> - <glossdef> - <para>Service Units are the actual Windows Server VMs instantiated by OpenStack and then - configured according to its Service Type (this may also correspond to one of predefined - Windows Server roles). - </para> - </glossdef> - </glossentry> - <glossentry> - <glossterm>Service Metadata</glossterm> - <glossdef> - <para>Service Metadata is a JSON-encoded definition of Environment, its Services and their - Service Units along with all their attributes. Service Metadata may describe both current - and the intended state of the Environment. - </para> - </glossdef> - </glossentry> - <glossentry> - <glossterm>Session</glossterm> - <glossdef> - <para>All changes to environment done in scope of Session. After all changes to Environment - state are accumulated, changes actually are applied only after session is deployed. - </para> - </glossdef> - </glossentry> - </glossary> - </section> - <section> - <title>Return codes and errors</title> - <para>All REST API calls return the natural HTTP response codes for the operations, e.g. a successful GET - returns a HTTP 200, a successful PUT returns a HTTP 201, a GET for a non-existent entity returns HTTP - 404, unauthorized operations return HTTP 401 or HTTP 403, internal errors return HTTP 500. - </para> - </section> - <section> - <title>Response of POSTs and PUTs</title> - <para>All POST and PUT requests by convention should return the created object (in the case of POST, with a - generated ID) as if it was requested by GET. - </para> - </section> - <section> - <title>Authentication</title> - <para>All requests include a Keystone authentication token header (X-Auth-Token). Clients must authenticate - with Keystone before interacting with the Glazier service. - </para> - </section> - <section> - <title>Workflow</title> - <figure xml:id="api_workflow"> - <title>Sample Workflow</title> - <mediaobject> - <imageobject role="fo"> - <imagedata fileref="figures/api_workflow.png" - contentwidth="5in"/> - </imageobject> - <imageobject role="html"> - <imagedata fileref="figures/api_workflow.png"/> - </imageobject> - </mediaobject> - </figure> - <para>Let’s review a sample workflow (series of API calls) for creating new Environment with Active - Directory Service deployment: - <orderedlist spacing="compact"> - <listitem> - <para>POST /environments/ - Creating new Environment</para> - </listitem> - <listitem> - <para>POST /environments/id/configure – Creating new configuration session for Environment - </para> - </listitem> - <listitem> - <para>POST /environments/id/activeDirectory – Creating new ActiveDirectory service</para> - </listitem> - <listitem> - <para>POST /environments/id/sessions/session_id/deploy – Saving and deploying changes</para> - </listitem> - </orderedlist> - </para> - </section> - <section> - <title>API</title> - <section> - <title>Environment API</title> - <para>This section describes API calls for Environment management.</para> - <table frame='all'> - <title>Environment Object</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="1*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Attribute</entry> - <entry>Type</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>id</entry> - <entry>guid</entry> - <entry>Unique ID</entry> - </row> - <row> - <entry>name</entry> - <entry>string</entry> - <entry>User-friendly name</entry> - </row> - <row> - <entry>created</entry> - <entry>datetime</entry> - <entry>Creation date and time in ISO format</entry> - </row> - <row> - <entry>updated</entry> - <entry>datetime</entry> - <entry>Modification date and time in ISO format</entry> - </row> - <row> - <entry>tenant_id</entry> - <entry>guid</entry> - <entry>Open Stack tenant id</entry> - </row> - <row> - <entry>status</entry> - <entry>string</entry> - <entry>Deployment status: draft, pending, inprogress, finished</entry> - </row> - </tbody> - </tgroup> - </table> - <section> - <title>Get a List of existing Environments</title> - <section> - <title>Call</title> - <table frame='all'> - <title>GET /environments Call</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="4*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Method</entry> - <entry>URI</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>GET</entry> - <entry>/environments</entry> - <entry>Get a list of existing Environments</entry> - </row> - </tbody> - </tgroup> - </table> - </section> - <section> - <title>Payload</title> - <para>None</para> - </section> - <section> - <title>Returns</title> - <para>This call returns list of environments. Only the basic properties are returned. For details see "Get Environment Detailed Information": - <programlisting> - <![CDATA[ - { - "environments": [ - { - "id": "0ce373a477f211e187a55404a662f968", - "name": "dc1", - "created": "2010-11-30T03:23:42Z", - "updated": "2010-11-30T03:23:44Z", - "tenant_id": "0849006f7ce94961b3aab4e46d6f229a" - }, - { - "id": "c697bd2429304820a928d145aa42af59", - "name": "dc2", - "created": "2010-11-30T03:23:42Z", - "updated": "2010-11-30T03:23:44Z", - "tenant_id": "0849006f7ce94961b3aab4e46d6f229a" - } - ] -} - ]]> - </programlisting> - </para> - </section> - </section> - <section> - <title>Create Environment instance</title> - <section> - <title>Call</title> - <table frame='all'> - <title>POST /environments Call</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="4*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Method</entry> - <entry>URI</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>POST</entry> - <entry>/environments</entry> - <entry>Create new Environment</entry> - </row> - </tbody> - </tgroup> - </table> - </section> - <section> - <title>Payload</title> - <programlisting> - <![CDATA[ -{ - "name": "env1" -} - ]]> - </programlisting> - </section> - <section> - <title>Returns</title> - <para>This call returns created environment: - <programlisting> - <![CDATA[ -{ - "id": "ce373a477f211e187a55404a662f968", - "name": "env1", - "created": "2010-11-30T03:23:42Z", - "updated": "2010-11-30T03:23:44Z", - "tenant_id": "0849006f7ce94961b3aab4e46d6f229a" -} - ]]> - </programlisting> - </para> - </section> - </section> - <section> - <title>Update Environment Instance</title> - <section> - <title>Call</title> - <table frame='all'> - <title>PUT /environments/&lt;id&gt; Call</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="4*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Method</entry> - <entry>URI</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>PUT</entry> - <entry>/environments/&lt;id&gt;</entry> - <entry>Update properties of Environment instance</entry> - </row> - </tbody> - </tgroup> - </table> - </section> - <section> - <title>Payload</title> - <programlisting> - <![CDATA[ -{ - "name": "env1-changed" -} - ]]> - </programlisting> - </section> - <section> - <title>Returns</title> - <para>This call returns modified environment object: - <programlisting> - <![CDATA[ -{ - "id": "ce373a477f211e187a55404a662f968", - "name": "env1-changed", - "created": "2010-11-30T03:23:42Z", - "updated": "2010-11-30T03:23:44Z", - "tenant_id": "0849006f7ce94961b3aab4e46d6f229a" -} - ]]> - </programlisting> - </para> - </section> - </section> - <section> - <title>Get Environment Instance Detailed Information</title> - <section> - <title>Call</title> - <table frame='all'> - <title>GET /environments/&lt;id&gt; Call</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="4*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Method</entry> - <entry>URI</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>GET</entry> - <entry>/environments/&lt;id&gt;</entry> - <entry>Returns detailed information about Environment including child entities</entry> - </row> - </tbody> - </tgroup> - </table> - </section> - <section> - <title>Payload</title> - <para>None</para> - </section> - <section> - <title>Returns</title> - <para>This call returns modified environment object: - <programlisting> - <![CDATA[ -{ - "id": "ce373a477f211e187a55404a662f968", - "name": "env1", - "created": "2010-11-30T03:23:42Z", - "updated": "2010-11-30T03:23:44Z", - "tenant_id": "0849006f7ce94961b3aab4e46d6f229a", - "status": "pending" -} - ]]> - </programlisting> - </para> - </section> - </section> - <section> - <title>Remove Environment</title> - <section> - <title>Call</title> - <table frame='all'> - <title>DELETE /environments/&lt;id&gt; Call</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="4*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Method</entry> - <entry>URI</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>DELETE</entry> - <entry>/environments/&lt;id&gt;</entry> - <entry>Remove specified Environment.</entry> - </row> - </tbody> - </tgroup> - </table> - </section> - <section> - <title>Payload</title> - <para>None</para> - </section> - <section> - <title>Returns</title> - <para>None</para> - </section> - </section> - </section> - <section> - <title>Environment Configuration API</title> - <para>Only one Environment can be configured at a time by only one user. This behavior archived by opening "configuration session" for some Environment by user, and locking this Environment for changes by other users. Only one open session per Environment is available.</para> - <table frame='all'> - <title>Configuration Session Object</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="1*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Attribute</entry> - <entry>Type</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>id</entry> - <entry>guid</entry> - <entry>Session unique ID</entry> - </row> - <row> - <entry>environment_id</entry> - <entry>guid</entry> - <entry>Environment that going to be modified during this session</entry> - </row> - <row> - <entry>created</entry> - <entry>datetime</entry> - <entry>Creation date and time in ISO format</entry> - </row> - <row> - <entry>updated</entry> - <entry>datetime</entry> - <entry>Modification date and time in ISO format</entry> - </row> - <row> - <entry>user_id</entry> - <entry>guid</entry> - <entry>Session owner guid</entry> - </row> - <row> - <entry>state</entry> - <entry>string</entry> - <entry>Session state. Could be: open, deploying, deployed</entry> - </row> - </tbody> - </tgroup> - </table> - <section> - <title>Get a List of Sessions</title> - <para>Only one open session can be for one Environment.</para> - <section> - <title>Call</title> - <table frame='all'> - <title>GET /environments/&lt;id&gt;/sessions Call</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="4*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Method</entry> - <entry>URI</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>GET</entry> - <entry>/environments/&lt;id&gt;/sessions</entry> - <entry>Get a list of open sessions</entry> - </row> - </tbody> - </tgroup> - </table> - </section> - <section> - <title>Payload</title> - <para>None</para> - </section> - <section> - <title>Returns</title> - <para>This call returns list of open sessions: - <programlisting> - <![CDATA[ - { - "sessions": [ - { - "id": "108bbd04084d4dc8a2e8986fa8fa5bf2", - "environment_id": "4dc8a2e8986fa8fa5bf24dc8a2e8986fa8", - "created": "2010-11-30T03:23:42Z", - "updated": "2010-11-30T03:23:54Z", - "user_id": "d7b501094caf4daab08469663a9e1a2b", - "state": "deployed" - }, - { - "id": "4aecdc2178b9430cbbb8db44fb7ac384", - "environment_id": "4dc8a2e8986fa8fa5bf24dc8a2e8986fa8", - "created": "2010-11-30T03:23:42Z", - "updated": "2010-11-30T03:23:54Z", - "user_id": "d7b501094caf4daab08469663a9e1a2b", - "state": "open" - } - ] -} - ]]> - </programlisting> - </para> - </section> - </section> - <section> - <title>Open session</title> - <para>During this call new working session is created, and session ID should be sent in header (X-Configuration-Session) to all next API calls.</para> - <section> - <title>Call</title> - <table frame='all'> - <title>POST /environments/&lt;id&gt;/configure Call</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="4*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Method</entry> - <entry>URI</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>POST</entry> - <entry>/environments/&lt;id&gt;/configure</entry> - <entry>Creating new configuration change session</entry> - </row> - </tbody> - </tgroup> - </table> - </section> - <section> - <title>Payload</title> - <para>None</para> - </section> - <section> - <title>Returns</title> - <para>This call returns created session: - <programlisting> - <![CDATA[ -{ - "id": "4aecdc2178b9430cbbb8db44fb7ac384", - "environment_id": "4dc8a2e8986fa8fa5bf24dc8a2e8986fa8", - "created": "2010-11-30T03:23:42Z", - "updated": "2010-11-30T03:23:54Z", - "user_id": "d7b501094caf4daab08469663a9e1a2b", - "state": "open" -} - ]]> - </programlisting> - </para> - </section> - </section> - <section> - <title>Deploy changes from Session</title> - <section> - <title>Call</title> - <table frame='all'> - <title>POST /environments/&lt;id&gt;/sessions/&lt;sessionId&gt;/deploy Call</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="4*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Method</entry> - <entry>URI</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>POST</entry> - <entry>/environments/&lt;id&gt;/sessions/&lt;sessionId&gt;/deploy</entry> - <entry>Deploying changes made in session with specified &lt;sessionId&gt;</entry> - </row> - </tbody> - </tgroup> - </table> - </section> - <section> - <title>Payload</title> - <para>None</para> - </section> - <section> - <title>Returns</title> - <para>This call returns deployed session: - <programlisting> - <![CDATA[ -{ - "id": "4aecdc2178b9430cbbb8db44fb7ac384", - "environment_id": "4dc8a2e8986fa8fa5bf24dc8a2e8986fa8", - "created": "2010-11-30T03:23:42Z", - "updated": "2010-11-30T03:23:54Z", - "user_id": "d7b501094caf4daab08469663a9e1a2b", - "state": "deploying" -} - ]]> - </programlisting> - </para> - </section> - </section> - <section> - <title>Get session information</title> - <section> - <title>Call</title> - <table frame='all'> - <title>GET /environments/&lt;id&gt;/sessions/&lt;sessionId&gt; Call</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="4*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Method</entry> - <entry>URI</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>GET</entry> - <entry>/environments/&lt;id&gt;/sessions/&lt;sessionId&gt;</entry> - <entry>Getting details about session with specified &lt;sessionId&gt;</entry> - </row> - </tbody> - </tgroup> - </table> - </section> - <section> - <title>Payload</title> - <para>None</para> - </section> - <section> - <title>Returns</title> - <para>This call returns session information: - <programlisting> - <![CDATA[ -{ - "id": "4aecdc2178b9430cbbb8db44fb7ac384", - "environment_id": "4dc8a2e8986fa8fa5bf24dc8a2e8986fa8", - "created": "2010-11-30T03:23:42Z", - "updated": "2010-11-30T03:23:54Z", - "user_id": "d7b501094caf4daab08469663a9e1a2b", - "state": "deploying" -} - ]]> - </programlisting> - </para> - </section> - </section> - <section> - <title>Delete Session </title> - <section> - <title>Call</title> - <table frame='all'> - <title>DELETE /environments/&lt;id&gt;/sessions/&lt;sessionId&gt; Call</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="4*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Method</entry> - <entry>URI</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>DELETE</entry> - <entry>/environments/&lt;id&gt;/sessions/&lt;sessionId&gt;</entry> - <entry>Delete session with specified &lt;sessionId&gt;</entry> - </row> - </tbody> - </tgroup> - </table> - </section> - <section> - <title>Payload</title> - <para>None</para> - </section> - <section> - <title>Returns</title> - <para>None</para> - </section> - </section> - </section> - <section> - <title>Active Directory API</title> - <para>This section describes API calls for Active Directory service management.</para> - <section> - <title>Get a List of existing Active Directory instances</title> - <table frame='all'> - <title>Active Directory Object</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="1*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Attribute</entry> - <entry>Type</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>id</entry> - <entry>guid</entry> - <entry>Unique ID</entry> - </row> - <row> - <entry>name</entry> - <entry>string</entry> - <entry>Domain name</entry> - </row> - <row> - <entry>created</entry> - <entry>datetime</entry> - <entry>Creation date and time in ISO format</entry> - </row> - <row> - <entry>updated</entry> - <entry>datetime</entry> - <entry>Modification date and time in ISO format</entry> - </row> - <row> - <entry>configuration</entry> - <entry>string</entry> - <entry>AD configuration: site, standalone, inTree</entry> - </row> - <row> - <entry>domain</entry> - <entry>string</entry> - <entry>Domain name (same as name)</entry> - </row> - <row> - <entry>units</entry> - <entry>object</entry> - <entry>Active Directory Unit object</entry> - </row> - </tbody> - </tgroup> - </table> - <table frame='all'> - <title>Active Directory Unit Object</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="1*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Attribute</entry> - <entry>Type</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>id</entry> - <entry>guid</entry> - <entry>Unique ID</entry> - </row> - <row> - <entry>isMaster</entry> - <entry>boolean</entry> - <entry>Is unit is master domain?</entry> - </row> - <row> - <entry>location</entry> - <entry>string</entry> - <entry>AvailabilityZone or specific physical datacenter.</entry> - </row> - </tbody> - </tgroup> - </table> - <section> - <title>Call</title> - <table frame='all'> - <title>GET /environments/&lt;id&gt;/activeDirectories Call</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="4*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Method</entry> - <entry>URI</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>GET</entry> - <entry>/environments/&lt;id&gt;/activeDirectories</entry> - <entry>Get a list of Active Directory instances</entry> - </row> - </tbody> - </tgroup> - </table> - </section> - <section> - <title>Payload</title> - <para>None</para> - </section> - <section> - <title>Returns</title> - <para>This call returns list of Active Directory instances: - <programlisting> - <![CDATA[ -{ - "activeDirectories": [{ - "id": "96365940588b479294fe8e6dc073db04", - "name": "acme.dc", - "created": "2010-11-30T03:23:42Z", - "updated": "2010-11-30T03:23:44Z", - "configuration": "standalone", - "units": [{ - "id": "d08887df15b94178b244904b506fe85b", - "isMaster": true, - "location": "west-dc" - }, { - "id": "dcf0de317e7046bea555539f19b8ea84", - "isMaster": false, - "location": "west-dc" - }] - }] -} - ]]> - </programlisting> - </para> - </section> - </section> - <section> - <title>Create Active Directory instance</title> - <table frame='all'> - <title>Active Directory Object</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="1*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Attribute</entry> - <entry>Type</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>name</entry> - <entry>string</entry> - <entry>Domain name</entry> - </row> - <row> - <entry>configuration</entry> - <entry>string</entry> - <entry>AD configuration: site, standalone, inTree</entry> - </row> - <row> - <entry>adminPassword</entry> - <entry>string</entry> - <entry>Password from domain administrator account</entry> - </row> - <row> - <entry>domain</entry> - <entry>string</entry> - <entry>Domain name (same as name)</entry> - </row> - <row> - <entry>units</entry> - <entry>object</entry> - <entry>Active Directory Unit object</entry> - </row> - </tbody> - </tgroup> - </table> - <table frame='all'> - <title>Active Directory Unit Object</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="1*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Attribute</entry> - <entry>Type</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>isMaster</entry> - <entry>boolean</entry> - <entry>Is unit is master domain?</entry> - </row> - <row> - <entry>recoveryPassword</entry> - <entry>string</entry> - <entry>Recovery password</entry> - </row> - <row> - <entry>location</entry> - <entry>string</entry> - <entry>AvailabilityZone or specific physical datacenter.</entry> - </row> - </tbody> - </tgroup> - </table> - <section> - <title>Call</title> - <table frame='all'> - <title>POST /environments/&lt;id&gt;/activeDirectories Call</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="4*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Method</entry> - <entry>URI</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>POST</entry> - <entry>/environments/&lt;id&gt;/activeDirectories</entry> - <entry>Create new Active Directory</entry> - </row> - </tbody> - </tgroup> - </table> - </section> - <section> - <title>Payload</title> - <programlisting> - <![CDATA[ -{ - "name": "acme.dc", - "configuration": "standalone", - "adminPassword": "password", - "domain": "acme.dc", - "units": [ - { - "isMaster": true, - "recoveryPassword": "password", - "location": "west-dc" - }, - { - "isMaster": false, - "recoveryPassword": "password", - "location": "west-dc" - } - ] -} - ]]> - </programlisting> - </section> - <section> - <title>Returns</title> - <para>This call returns created active directory domain: - <programlisting> - <![CDATA[ -{ - "id": "96365940588b479294fe8e6dc073db04", - "name": "acme.dc", - "created": "2010-11-30T03:23:42Z", - "updated": "2010-11-30T03:23:44Z", - "domain": "acme.dc", - "configuration": "standalone", - "units": [{ - "id": "d08887df15b94178b244904b506fe85b", - "isMaster": true, - "location": "west-dc" - }, { - "id": "dcf0de317e7046bea555539f19b8ea84", - "isMaster": false, - "location": "west-dc" - }] -} - ]]> - </programlisting> - </para> - </section> - </section> - <section> - <title>Update Active Directory instance</title> - <table frame='all'> - <title>Active Directory Object</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="1*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Attribute</entry> - <entry>Type</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>id</entry> - <entry>guid</entry> - <entry>Unique ID</entry> - </row> - <row> - <entry>name</entry> - <entry>string</entry> - <entry>Domain name</entry> - </row> - <row> - <entry>configuration</entry> - <entry>string</entry> - <entry>AD configuration: site, standalone, inTree</entry> - </row> - <row> - <entry>adminPassword</entry> - <entry>string</entry> - <entry>Password from domain administrator account</entry> - </row> - <row> - <entry>domain</entry> - <entry>string</entry> - <entry>Domain name (same as name)</entry> - </row> - <row> - <entry>units</entry> - <entry>object</entry> - <entry>Active Directory Unit object</entry> - </row> - </tbody> - </tgroup> - </table> - <table frame='all'> - <title>Active Directory Unit Object</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="1*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Attribute</entry> - <entry>Type</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>id</entry> - <entry>guid</entry> - <entry>Unique ID</entry> - </row> - <row> - <entry>isMaster</entry> - <entry>boolean</entry> - <entry>Is unit is master domain?</entry> - </row> - <row> - <entry>recoveryPassword</entry> - <entry>string</entry> - <entry>Recovery password</entry> - </row> - <row> - <entry>location</entry> - <entry>string</entry> - <entry>AvailabilityZone or specific physical datacenter.</entry> - </row> - </tbody> - </tgroup> - </table> - <section> - <title>Call</title> - <table frame='all'> - <title>PUT /environments/&lt;id&gt;/activeDirectories/&lt;serviceId&gt; Call</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="4*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Method</entry> - <entry>URI</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>PUT</entry> - <entry>/environments/&lt;id&gt;/activeDirectories/&lt;serviceId&gt;</entry> - <entry>Update existing Active Directory</entry> - </row> - </tbody> - </tgroup> - </table> - </section> - <section> - <title>Payload</title> - <programlisting> - <![CDATA[ -{ - "name": "acme.dc", - "configuration": "standalone", - "adminPassword": "password", - "domain": "acme.dc", - "units": [ - { - "isMaster": true, - "recoveryPassword": "new-rpassword", - "location": "west-dc" - }, - { - "isMaster": false, - "recoveryPassword": "new-rpassword", - "location": "west-dc" - } - ] -} - ]]> - </programlisting> - </section> - <section> - <title>Returns</title> - <para>This call returns updated active directory domain: - <programlisting> - <![CDATA[ -{ - "id": "96365940588b479294fe8e6dc073db04", - "name": "acme.dc", - "created": "2010-11-30T03:23:42Z", - "updated": "2010-11-30T03:23:44Z", - "configuration": "standalone", - "domain": "acme.dc", - "units": [{ - "id": "d08887df15b94178b244904b506fe85b", - "isMaster": true, - "location": "west-dc" - }, { - "id": "dcf0de317e7046bea555539f19b8ea84", - "isMaster": false, - "location": "west-dc" - }] -} - ]]> - </programlisting> - </para> - </section> - </section> - <section> - <title>Get Information about Active Directory instance</title> - <table frame='all'> - <title>Active Directory Object</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="1*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Attribute</entry> - <entry>Type</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>id</entry> - <entry>guid</entry> - <entry>Unique ID</entry> - </row> - <row> - <entry>name</entry> - <entry>string</entry> - <entry>Domain name</entry> - </row> - <row> - <entry>created</entry> - <entry>datetime</entry> - <entry>Creation date and time in ISO format</entry> - </row> - <row> - <entry>updated</entry> - <entry>datetime</entry> - <entry>Modification date and time in ISO format</entry> - </row> - <row> - <entry>configuration</entry> - <entry>string</entry> - <entry>AD configuration: site, standalone, inTree</entry> - </row> - <row> - <entry>domain</entry> - <entry>string</entry> - <entry>Domain name (same as name)</entry> - </row> - <row> - <entry>units</entry> - <entry>object</entry> - <entry>Active Directory Unit object</entry> - </row> - </tbody> - </tgroup> - </table> - <table frame='all'> - <title>Active Directory Unit Object</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="1*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Attribute</entry> - <entry>Type</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>id</entry> - <entry>guid</entry> - <entry>Unique ID</entry> - </row> - <row> - <entry>isMaster</entry> - <entry>boolean</entry> - <entry>Is unit is master domain?</entry> - </row> - <row> - <entry>location</entry> - <entry>string</entry> - <entry>AvailabilityZone or specific physical datacenter.</entry> - </row> - </tbody> - </tgroup> - </table> - <section> - <title>Call</title> - <table frame='all'> - <title>GET /environments/&lt;id&gt;/activeDirectories/&lt;serviceId&gt; Call</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="4*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Method</entry> - <entry>URI</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>GET</entry> - <entry>/environments/&lt;id&gt;/activeDirectories/&lt;serviceId&gt;</entry> - <entry>Return specified Active Directory instance</entry> - </row> - </tbody> - </tgroup> - </table> - </section> - <section> - <title>Payload</title> - <para>None</para> - </section> - <section> - <title>Returns</title> - <para>This call returns modified environment object: - <programlisting> - <![CDATA[ -{ - "id": "96365940588b479294fe8e6dc073db04", - "name": "acme.dc", - "created": "2010-11-30T03:23:42Z", - "updated": "2010-11-30T03:23:44Z", - "configuration": "standalone", - "domain": "acme.dc", - "units": [{ - "id": "d08887df15b94178b244904b506fe85b", - "isMaster": true, - "location": "west-dc" - }, { - "id": "dcf0de317e7046bea555539f19b8ea84", - "isMaster": false, - "location": "west-dc" - }] -} - ]]> - </programlisting> - </para> - </section> - </section> - </section> - <section> - <title>Web Server API</title> - <para>This section describes API calls for managing Windows web-server software – IIS.</para> - <table frame='all'> - <title>Web Server Object</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="1*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Attribute</entry> - <entry>Type</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>id</entry> - <entry>guid</entry> - <entry>Unique ID</entry> - </row> - <row> - <entry>name</entry> - <entry>string</entry> - <entry>User-friendly name</entry> - </row> - <row> - <entry>created</entry> - <entry>datetime</entry> - <entry>Creation date and time in ISO format</entry> - </row> - <row> - <entry>updated</entry> - <entry>datetime</entry> - <entry>Modification date and time in ISO format</entry> - </row> - <row> - <entry>domain</entry> - <entry>string</entry> - <entry>Domain name (same as name)</entry> - </row> - <row> - <entry>units</entry> - <entry>object</entry> - <entry>Web Server Unit object</entry> - </row> - </tbody> - </tgroup> - </table> - <table frame='all'> - <title>Web Server Unit Object</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="1*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Attribute</entry> - <entry>Type</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>id</entry> - <entry>guid</entry> - <entry>Unique ID</entry> - </row> - <row> - <entry>endpoint</entry> - <entry>object</entry> - <entry>Unit Endpoint</entry> - </row> - <row> - <entry>location</entry> - <entry>string</entry> - <entry>AvailabilityZone or specific physical datacenter.</entry> - </row> - </tbody> - </tgroup> - </table> - <table frame='all'> - <title>Web Server Unit Endpoint Object</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="1*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Attribute</entry> - <entry>Type</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>host</entry> - <entry>string</entry> - <entry>Host address for IIS Management Console connection</entry> - </row> - </tbody> - </tgroup> - </table> - <section> - <title>Get a List of existing Web Servers</title> - <section> - <title>Call</title> - <table frame='all'> - <title>GET /environments/&lt;id&gt;/webServers Call</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="4*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Method</entry> - <entry>URI</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>GET</entry> - <entry>/environments/&lt;id&gt;/webServers</entry> - <entry>Get a list of existing Web Servers</entry> - </row> - </tbody> - </tgroup> - </table> - </section> - <section> - <title>Payload</title> - <para>None</para> - </section> - <section> - <title>Returns</title> - <para>This call returns list of web servers: - <programlisting> - <![CDATA[ -{ - "webServers": - [ - { - "id": "0ce373a477f211e187a55404a662f968", - "name": "frontend", - "created": "2010-11-30T03:23:42Z", - "updated": "2010-11-30T03:23:44Z", - "domain": "ACME", - "units": [{ - "id": "1bf3491c409b4541b6f18ea5988a6437", - "endpoint": { - "host": "10.0.0.2" - }, - "location": "west-dc" - }] - }, - { - "id": "c697bd2429304820a928d145aa42af59", - "name": "backend", - "created": "2010-11-30T03:23:42Z", - "updated": "2010-11-30T03:23:44Z", - "domain": "ACME" , - "units": [{ - "id": "eb32f97866d24001baa430cb34e4049f", - "endpoint": { - "host": "10.0.0.3" - }, - "location": "west-dc" - }] - } - ] -} ]]> - </programlisting> - </para> - </section> - </section> - <section> - <title>Create Web Server instance</title> - <section> - <title>Call</title> - <table frame='all'> - <title>POST /environments/&lt;id&gt;/webServers Call</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="4*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Method</entry> - <entry>URI</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>POST</entry> - <entry>/environments/&lt;id&gt;/webServers</entry> - <entry>Create new Web Server</entry> - </row> - </tbody> - </tgroup> - </table> - </section> - <section> - <title>Payload</title> - <programlisting> - <![CDATA[ -{ - "name": "frontend", - "domain": { - "name": "ACME", - "credentials": { - "username": "admin", - "password": "password" - } - }, - "credentials": { - "username": "admin", - "password": "password" - } - "location": "west-dc" -} - ]]> - </programlisting> - </section> - <section> - <title>Returns</title> - <para>This call returns created web server: - <programlisting> - <![CDATA[ -{ - "id": "ce373a477f211e187a55404a662f968", - "name": "frontend", - "created": "2010-11-30T03:23:42Z", - "updated": "2010-11-30T03:23:44Z", - "domain": "ACME", - "units": [{ - "id": "1bf3491c409b4541b6f18ea5988a6437", - "location": "west-dc" - }] -} - ]]> - </programlisting> - </para> - </section> - </section> - <section> - <title>Update Web Server Instance</title> - <section> - <title>Call</title> - <table frame='all'> - <title>PUT /environments/&lt;id&gt;/webServers/&lt;serviceId&gt; Call</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="4*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Method</entry> - <entry>URI</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>PUT</entry> - <entry>/environments/&lt;id&gt;/webServers/&lt;serviceId&gt;</entry> - <entry>Update properties of WebServer instance</entry> - </row> - </tbody> - </tgroup> - </table> - </section> - <section> - <title>Payload</title> - <programlisting> - <![CDATA[ -{ - "name": "frontend-changed", - "domain": { - "name": "ACME", - "username": "admin", - "password": "password" - }, - "credentials": { - "username": "admin", - "password": "password" - } -} - ]]> - </programlisting> - </section> - <section> - <title>Returns</title> - <para>This call returns modified web server object: - <programlisting> - <![CDATA[ -{ - "id": "ce373a477f211e187a55404a662f968", - "name": "frontend", - "created": "2010-11-30T03:23:42Z", - "updated": "2010-11-30T03:23:44Z", - "domain": "ACME", - "units": [{ - "id": "1bf3491c409b4541b6f18ea5988a6437", - "location": "west-dc" - }] -} - ]]> - </programlisting> - </para> - </section> - </section> - <section> - <title>Get Web Server Instance Detailed Information</title> - <section> - <title>Call</title> - <table frame='all'> - <title>GET /environments/&lt;id&gt;/webServers/&lt;serviceId&gt; Call</title> - <tgroup cols='3' align='left' colsep='1' rowsep='1'> - <colspec colnum="1" colname="col1" colwidth="1*"/> - <colspec colnum="2" colname="col2" colwidth="4*"/> - <colspec colnum="3" colname="col3" colwidth="4*"/> - <thead> - <row> - <entry>Method</entry> - <entry>URI</entry> - <entry>Description</entry> - </row> - </thead> - <tbody> - <row> - <entry>GET</entry> - <entry>/environments/&lt;id&gt;/webServers/&lt;serviceId&gt;</entry> - <entry>Returns detailed information about Web Server</entry> - </row> - </tbody> - </tgroup> - </table> - </section> - <section> - <title>Payload</title> - <para>None</para> - </section> - <section> - <title>Returns</title> - <para>This call returns modified environment object: - <programlisting> - <![CDATA[ -{ - "id": "c697bd2429304820a928d145aa42af59", - "name": "backend", - "created": "2010-11-30T03:23:42Z", - "updated": "2010-11-30T03:23:44Z", - "domain": "ACME" , - "units": [{ - "id": "eb32f97866d24001baa430cb34e4049f", - "endpoint": { - "host": "10.0.0.3" - }, - "location": "west-dc" - }] -} - ]]> - </programlisting> - </para> - </section> - </section> - </section> - </section> - </chapter> -</book> diff --git a/WindowsAgent/packages/repositories.config b/packages/repositories.config similarity index 100% rename from WindowsAgent/packages/repositories.config rename to packages/repositories.config diff --git a/python-glazierclient/.gitignore b/python-glazierclient/.gitignore deleted file mode 100644 index f5f39680..00000000 --- a/python-glazierclient/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -#IntelJ Idea -.idea/ - -#virtualenv -.venv/ - -#Build results -build/ -dist/ -*.egg-info/ - -#Python -*.pyc - -#Translation build -*.mo -*.pot - -#SQLite Database files -*.sqlite - -#Autogenerated Documentation -doc/source/api \ No newline at end of file diff --git a/python-glazierclient/README.rst b/python-glazierclient/README.rst deleted file mode 100644 index b7a3f782..00000000 --- a/python-glazierclient/README.rst +++ /dev/null @@ -1,9 +0,0 @@ -Python bindings to the Glazier API -===================== -This is a client library for Glazier built on the Glazier API. It -provides a Python API (the ``glazierclient`` module) and a command-line tool -(``glazier``). - -SEE ALSO --------- -* `Glazier <http://glazier.mirantis.com>`__ diff --git a/python-glazierclient/doc/source/_static/.placeholder b/python-glazierclient/doc/source/_static/.placeholder deleted file mode 100755 index e69de29b..00000000 diff --git a/python-glazierclient/doc/source/_templates/.placeholder b/python-glazierclient/doc/source/_templates/.placeholder deleted file mode 100755 index e69de29b..00000000 diff --git a/python-glazierclient/doc/source/_theme/theme.conf b/python-glazierclient/doc/source/_theme/theme.conf deleted file mode 100755 index 9a8facf4..00000000 --- a/python-glazierclient/doc/source/_theme/theme.conf +++ /dev/null @@ -1,2 +0,0 @@ -[theme] -inherit = default \ No newline at end of file diff --git a/python-glazierclient/doc/source/conf.py b/python-glazierclient/doc/source/conf.py deleted file mode 100644 index 38d8e651..00000000 --- a/python-glazierclient/doc/source/conf.py +++ /dev/null @@ -1,73 +0,0 @@ -# -*- coding: utf-8 -*- -# -import os - -project = 'python-glazierclient' - -# -- General configuration ---------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', - 'sphinx.ext.intersphinx', - 'sphinx.ext.coverage', - 'sphinx.ext.pngmath', - 'sphinx.ext.ifconfig', - 'sphinx.ext.graphviz'] - -# autodoc generation is a bit aggressive and a nuisance when doing heavy -# text edit cycles. -# execute "export SPHINX_DEBUG=1" in your terminal to disable - -# Add any paths that contain templates here, relative to this directory. -templates_path = [] -if os.getenv('HUDSON_PUBLISH_DOCS'): - templates_path = ['_ga', '_templates'] -else: - templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -copyright = u'Mirantis, Inc' -exclude_trees = ['api'] - -# If true, '()' will be appended to :func: etc. cross-reference text. -add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -add_module_names = True - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# -- Options for HTML output -------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -html_theme = 'default' - -# Output file base name for HTML help builder. -htmlhelp_basename = '%sdoc' % project - - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass -# [howto/manual]). -latex_documents = [ - ( - 'index', - '%s.tex' % project, - u'%s Documentation' % project, - u'Mirantis, Inc', - 'manual' - ), -] - -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'http://docs.python.org/': None} diff --git a/python-glazierclient/doc/source/index.rst b/python-glazierclient/doc/source/index.rst deleted file mode 100644 index 395524e6..00000000 --- a/python-glazierclient/doc/source/index.rst +++ /dev/null @@ -1,48 +0,0 @@ -.. - Copyright (c) 2013 Mirantis, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); you may - not use this file except in compliance with the License. You may obtain - a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - License for the specific language governing permissions and limitations - under the License. - -================== -Glazier API Client -================== -In order to use the python api directly, you must first obtain an auth token and identify which endpoint you wish to speak to. Once you have done so, you can use the API like so:: - - >>> from glazierclient import Client - >>> glazier = Client('1', endpoint=GLAZIER_URL, token=OS_AUTH_TOKEN) -... - - -Command-line Tool -================= -In order to use the CLI, you must provide your OpenStack username, password, tenant, and auth endpoint. Use the corresponding configuration options (``--os-username``, ``--os-password``, ``--os-tenant-id``, and ``--os-auth-url``) or set them in environment variables:: - - export OS_USERNAME=user - export OS_PASSWORD=pass - export OS_TENANT_ID=b363706f891f48019483f8bd6503c54b - export OS_AUTH_URL=http://auth.example.com:5000/v2.0 - -The command line tool will attempt to reauthenticate using your provided credentials for every request. You can override this behavior by manually supplying an auth token using ``--os-image-url`` and ``--os-auth-token``. You can alternatively set these environment variables:: - - export GLAZIER_URL=http://glazier.example.org:8082/ - export OS_AUTH_TOKEN=3bcc3d3a03f44e3d8377f9247b0ad155 - -Once you've configured your authentication parameters, you can run ``glazier help`` to see a complete listing of available commands. - - -Release Notes -============= - -0.1.0 ------ -* Initial release diff --git a/python-glazierclient/glazierclient/__init__.py b/python-glazierclient/glazierclient/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/python-glazierclient/glazierclient/client.py b/python-glazierclient/glazierclient/client.py deleted file mode 100644 index 84779d10..00000000 --- a/python-glazierclient/glazierclient/client.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -from glazierclient.common import utils - - -def Client(version, *args, **kwargs): - module = utils.import_versioned_module(version, 'client') - client_class = getattr(module, 'Client') - return client_class(*args, **kwargs) diff --git a/python-glazierclient/glazierclient/common/__init__.py b/python-glazierclient/glazierclient/common/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/python-glazierclient/glazierclient/common/base.py b/python-glazierclient/glazierclient/common/base.py deleted file mode 100644 index e92def98..00000000 --- a/python-glazierclient/glazierclient/common/base.py +++ /dev/null @@ -1,166 +0,0 @@ -# Copyright 2012 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Base utilities to build API operation managers and objects on top of. -""" - -import copy - - -# Python 2.4 compat -try: - all -except NameError: - def all(iterable): - return True not in (not x for x in iterable) - - -def getid(obj): - """ - Abstracts the common pattern of allowing both an object or an object's ID - (UUID) as a parameter when dealing with relationships. - """ - try: - return obj.id - except AttributeError: - return obj - - -class Manager(object): - """ - Managers interact with a particular type of API (servers, flavors, images, - etc.) and provide CRUD operations for them. - """ - resource_class = None - - def __init__(self, api): - self.api = api - - def _list(self, url, response_key=None, obj_class=None, - body=None, headers={}): - - resp, body = self.api.json_request('GET', url, headers=headers) - - if obj_class is None: - obj_class = self.resource_class - - if response_key: - if not response_key in body: - body[response_key] = [] - data = body[response_key] - else: - data = body - return [obj_class(self, res, loaded=True) for res in data if res] - - def _delete(self, url, headers={}): - self.api.raw_request('DELETE', url, headers=headers) - - def _update(self, url, body, response_key=None): - resp, body = self.api.json_request('PUT', url, body=body) - # PUT requests may not return a body - if body: - if response_key: - return self.resource_class(self, body[response_key]) - return self.resource_class(self, body) - - def _create(self, url, body=None, response_key=None, - return_raw=False, headers={}): - - if body: - resp, body = self.api.json_request('POST', url, - body=body, headers=headers) - else: - resp, body = self.api.json_request('POST', url, headers=headers) - if return_raw: - if response_key: - return body[response_key] - return body - if response_key: - return self.resource_class(self, body[response_key]) - return self.resource_class(self, body) - - def _get(self, url, response_key=None, return_raw=False): - resp, body = self.api.json_request('GET', url) - if return_raw: - if response_key: - return body[response_key] - return body - if response_key: - return self.resource_class(self, body[response_key]) - return self.resource_class(self, body) - - -class Resource(object): - """ - A resource represents a particular instance of an object (tenant, user, - etc). This is pretty much just a bag for attributes. - - :param manager: Manager object - :param info: dictionary representing resource attributes - :param loaded: prevent lazy-loading if set to True - """ - def __init__(self, manager, info, loaded=False): - self.manager = manager - self._info = info - self._add_details(info) - self._loaded = loaded - - def _add_details(self, info): - for (k, v) in info.iteritems(): - setattr(self, k, v) - - def __getattr__(self, k): - if k not in self.__dict__: - # NOTE(bcwaldon): disallow lazy-loading if already loaded once - if not self.is_loaded(): - self.get() - return self.__getattr__(k) - - raise AttributeError(k) - else: - return self.__dict__[k] - - def __repr__(self): - reprkeys = sorted(k for k in self.__dict__.keys() if k[0] != '_' and - k != 'manager') - info = ", ".join("%s=%s" % (k, getattr(self, k)) for k in reprkeys) - return "<%s %s>" % (self.__class__.__name__, info) - - def get(self): - # set_loaded() first ... so if we have to bail, we know we tried. - self.set_loaded(True) - if not hasattr(self.manager, 'get'): - return - - new = self.manager.get(self.id) - if new: - self._add_details(new._info) - - def __eq__(self, other): - if not isinstance(other, self.__class__): - return False - if hasattr(self, 'id') and hasattr(other, 'id'): - return self.id == other.id - return self._info == other._info - - def is_loaded(self): - return self._loaded - - def set_loaded(self, val): - self._loaded = val - - def to_dict(self): - return copy.deepcopy(self._info) diff --git a/python-glazierclient/glazierclient/common/exceptions.py b/python-glazierclient/glazierclient/common/exceptions.py deleted file mode 100644 index d3d3cab6..00000000 --- a/python-glazierclient/glazierclient/common/exceptions.py +++ /dev/null @@ -1,163 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import sys - - -class BaseException(Exception): - """An error occurred.""" - def __init__(self, message=None): - self.message = message - - def __str__(self): - return self.message or self.__class__.__doc__ - - -class CommandError(BaseException): - """Invalid usage of CLI""" - - -class InvalidEndpoint(BaseException): - """The provided endpoint is invalid.""" - - -class CommunicationError(BaseException): - """Unable to communicate with server.""" - - -class ClientException(Exception): - """DEPRECATED""" - - -class HTTPException(ClientException): - """Base exception for all HTTP-derived exceptions""" - code = 'N/A' - - def __init__(self, details=None): - self.details = details - - def __str__(self): - return "%s (HTTP %s)" % (self.__class__.__name__, self.code) - - -class HTTPMultipleChoices(HTTPException): - code = 300 - - def __str__(self): - self.details = ("Requested version of OpenStack Images API is not" - "available.") - return "%s (HTTP %s) %s" % (self.__class__.__name__, self.code, - self.details) - - -class BadRequest(HTTPException): - """DEPRECATED""" - code = 400 - - -class HTTPBadRequest(BadRequest): - pass - - -class Unauthorized(HTTPException): - """DEPRECATED""" - code = 401 - - -class HTTPUnauthorized(Unauthorized): - pass - - -class Forbidden(HTTPException): - """DEPRECATED""" - code = 403 - - -class HTTPForbidden(Forbidden): - pass - - -class NotFound(HTTPException): - """DEPRECATED""" - code = 404 - - -class HTTPNotFound(NotFound): - pass - - -class HTTPMethodNotAllowed(HTTPException): - code = 405 - - -class Conflict(HTTPException): - """DEPRECATED""" - code = 409 - - -class HTTPConflict(Conflict): - pass - - -class OverLimit(HTTPException): - """DEPRECATED""" - code = 413 - - -class HTTPOverLimit(OverLimit): - pass - - -class HTTPInternalServerError(HTTPException): - code = 500 - - -class HTTPNotImplemented(HTTPException): - code = 501 - - -class HTTPBadGateway(HTTPException): - code = 502 - - -class ServiceUnavailable(HTTPException): - """DEPRECATED""" - code = 503 - - -class HTTPServiceUnavailable(ServiceUnavailable): - pass - - -#NOTE(bcwaldon): Build a mapping of HTTP codes to corresponding exception -# classes -_code_map = {} -for obj_name in dir(sys.modules[__name__]): - if obj_name.startswith('HTTP'): - obj = getattr(sys.modules[__name__], obj_name) - _code_map[obj.code] = obj - - -def from_response(response): - """Return an instance of an HTTPException based on httplib response.""" - cls = _code_map.get(response.status, HTTPException) - return cls() - - -class NoTokenLookupException(Exception): - """DEPRECATED""" - pass - - -class EndpointNotFound(Exception): - """DEPRECATED""" - pass diff --git a/python-glazierclient/glazierclient/common/http.py b/python-glazierclient/glazierclient/common/http.py deleted file mode 100644 index 3f1e26f6..00000000 --- a/python-glazierclient/glazierclient/common/http.py +++ /dev/null @@ -1,275 +0,0 @@ -# Copyright 2012 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy -import httplib -import logging -import socket -import StringIO -import urlparse - -import os -from glazierclient.common import exceptions - - -try: - import ssl -except ImportError: - #TODO(bcwaldon): Handle this failure more gracefully - pass - -try: - import json -except ImportError: - import simplejson as json - -# Python 2.5 compat fix -if not hasattr(urlparse, 'parse_qsl'): - import cgi - urlparse.parse_qsl = cgi.parse_qsl - -LOG = logging.getLogger(__name__) -USER_AGENT = 'python-glazierclient' -CHUNKSIZE = 1024 * 64 # 64kB - - -class HTTPClient(object): - - def __init__(self, endpoint, **kwargs): - self.endpoint = endpoint - self.auth_token = kwargs.get('token') - self.connection_params = self.get_connection_params(endpoint, **kwargs) - - @staticmethod - def get_connection_params(endpoint, **kwargs): - parts = urlparse.urlparse(endpoint) - - _args = (parts.hostname, parts.port, parts.path) - _kwargs = {'timeout': float(kwargs.get('timeout', 600))} - - if parts.scheme == 'https': - _class = VerifiedHTTPSConnection - _kwargs['ca_file'] = kwargs.get('ca_file', None) - _kwargs['cert_file'] = kwargs.get('cert_file', None) - _kwargs['key_file'] = kwargs.get('key_file', None) - _kwargs['insecure'] = kwargs.get('insecure', False) - elif parts.scheme == 'http': - _class = httplib.HTTPConnection - else: - msg = 'Unsupported scheme: %s' % parts.scheme - raise exceptions.InvalidEndpoint(msg) - - return (_class, _args, _kwargs) - - def get_connection(self): - _class = self.connection_params[0] - try: - return _class(*self.connection_params[1], - **self.connection_params[2]) - except httplib.InvalidURL: - raise exceptions.InvalidEndpoint() - - def log_curl_request(self, method, url, kwargs): - curl = ['curl -i -X %s' % method] - - for (key, value) in kwargs['headers'].items(): - header = '-H \'%s: %s\'' % (key, value) - curl.append(header) - - conn_params_fmt = [ - ('key_file', '--key %s'), - ('cert_file', '--cert %s'), - ('ca_file', '--cacert %s'), - ] - for (key, fmt) in conn_params_fmt: - value = self.connection_params[2].get(key) - if value: - curl.append(fmt % value) - - if self.connection_params[2].get('insecure'): - curl.append('-k') - - if 'body' in kwargs: - curl.append('-d \'%s\'' % kwargs['body']) - - curl.append('%s%s' % (self.endpoint, url)) - LOG.debug(' '.join(curl)) - - @staticmethod - def log_http_response(resp, body=None): - status = (resp.version / 10.0, resp.status, resp.reason) - dump = ['\nHTTP/%.1f %s %s' % status] - dump.extend(['%s: %s' % (k, v) for k, v in resp.getheaders()]) - dump.append('') - if body: - dump.extend([body, '']) - LOG.debug('\n'.join(dump)) - - def _http_request(self, url, method, **kwargs): - """ Send an http request with the specified characteristics. - - Wrapper around httplib.HTTP(S)Connection.request to handle tasks such - as setting headers and error handling. - """ - # Copy the kwargs so we can reuse the original in case of redirects - kwargs['headers'] = copy.deepcopy(kwargs.get('headers', {})) - kwargs['headers'].setdefault('User-Agent', USER_AGENT) - if self.auth_token: - kwargs['headers'].setdefault('X-Auth-Token', self.auth_token) - - self.log_curl_request(method, url, kwargs) - conn = self.get_connection() - - try: - conn_params = self.connection_params[1][2] - conn_url = os.path.normpath('%s/%s' % (conn_params, url)) - conn.request(method, conn_url, **kwargs) - resp = conn.getresponse() - except socket.gaierror as e: - message = "Error finding address for %(url)s: %(e)s" % locals() - raise exceptions.InvalidEndpoint(message=message) - except (socket.error, socket.timeout) as e: - endpoint = self.endpoint - message = "Error communicating with %(endpoint)s %(e)s" % locals() - raise exceptions.CommunicationError(message=message) - - body_iter = ResponseBodyIterator(resp) - - # Read body into string if it isn't obviously image data - if resp.getheader('content-type', None) != 'application/octet-stream': - body_str = ''.join([chunk for chunk in body_iter]) - self.log_http_response(resp, body_str) - body_iter = StringIO.StringIO(body_str) - else: - self.log_http_response(resp) - - if 400 <= resp.status < 600: - LOG.warn("Request returned failure status.") - raise exceptions.from_response(resp) - elif resp.status in (301, 302, 305): - # Redirected. Reissue the request to the new location. - return self._http_request(resp['location'], method, **kwargs) - elif resp.status == 300: - raise exceptions.from_response(resp) - - return resp, body_iter - - def json_request(self, method, url, **kwargs): - kwargs.setdefault('headers', {}) - kwargs['headers'].setdefault('Content-Type', 'application/json') - kwargs['headers'].setdefault('Accept', 'application/json') - - if 'body' in kwargs: - kwargs['body'] = json.dumps(kwargs['body']) - - resp, body_iter = self._http_request(url, method, **kwargs) - - if 'application/json' in resp.getheader('content-type', None): - body = ''.join([chunk for chunk in body_iter]) - try: - body = json.loads(body) - except ValueError: - LOG.error('Could not decode response body as JSON') - else: - body = None - - return resp, body - - def raw_request(self, method, url, **kwargs): - kwargs.setdefault('headers', {}) - kwargs['headers'].setdefault('Content-Type', - 'application/octet-stream') - return self._http_request(url, method, **kwargs) - - -class VerifiedHTTPSConnection(httplib.HTTPSConnection): - """httplib-compatibile connection using client-side SSL authentication - - :see http://code.activestate.com/recipes/ - 577548-https-httplib-client-connection-with-certificate-v/ - """ - - def __init__(self, host, port, key_file=None, cert_file=None, - ca_file=None, timeout=None, insecure=False): - httplib.HTTPSConnection.__init__(self, host, port, key_file=key_file, - cert_file=cert_file) - self.key_file = key_file - self.cert_file = cert_file - if ca_file is not None: - self.ca_file = ca_file - else: - self.ca_file = self.get_system_ca_file() - self.timeout = timeout - self.insecure = insecure - - def connect(self): - """ - Connect to a host on a given (SSL) port. - If ca_file is pointing somewhere, use it to check Server Certificate. - - Redefined/copied and extended from httplib.py:1105 (Python 2.6.x). - This is needed to pass cert_reqs=ssl.CERT_REQUIRED as parameter to - ssl.wrap_socket(), which forces SSL to check server certificate against - our client certificate. - """ - sock = socket.create_connection((self.host, self.port), self.timeout) - - if self._tunnel_host: - self.sock = sock - self._tunnel() - - if self.insecure is True: - kwargs = {'cert_reqs': ssl.CERT_NONE} - else: - kwargs = {'cert_reqs': ssl.CERT_REQUIRED, 'ca_certs': self.ca_file} - - if self.cert_file: - kwargs['certfile'] = self.cert_file - if self.key_file: - kwargs['keyfile'] = self.key_file - - self.sock = ssl.wrap_socket(sock, **kwargs) - - @staticmethod - def get_system_ca_file(): - """"Return path to system default CA file""" - # Standard CA file locations for Debian/Ubuntu, RedHat/Fedora, - # Suse, FreeBSD/OpenBSD - ca_path = ['/etc/ssl/certs/ca-certificates.crt', - '/etc/pki/tls/certs/ca-bundle.crt', - '/etc/ssl/ca-bundle.pem', - '/etc/ssl/cert.pem'] - for ca in ca_path: - if os.path.exists(ca): - return ca - return None - - -class ResponseBodyIterator(object): - """A class that acts as an iterator over an HTTP response.""" - - def __init__(self, resp): - self.resp = resp - - def __iter__(self): - while True: - yield self.next() - - def next(self): - chunk = self.resp.read(CHUNKSIZE) - if chunk: - return chunk - else: - raise StopIteration() diff --git a/python-glazierclient/glazierclient/common/utils.py b/python-glazierclient/glazierclient/common/utils.py deleted file mode 100644 index 7063e65f..00000000 --- a/python-glazierclient/glazierclient/common/utils.py +++ /dev/null @@ -1,119 +0,0 @@ -# Copyright 2012 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import sys -import uuid - -import os -from glazierclient.common import exceptions -import prettytable -from glazierclient.openstack.common import importutils - - -# Decorator for cli-args -def arg(*args, **kwargs): - def _decorator(func): - # Because of the sematics of decorator composition if we just append - # to the options list positional options will appear to be backwards. - func.__dict__.setdefault('arguments', []).insert(0, (args, kwargs)) - return func - return _decorator - - -def pretty_choice_list(l): - return ', '.join("'%s'" % i for i in l) - - -def print_list(objs, fields, field_labels, formatters={}, sortby=0): - pt = prettytable.PrettyTable([f for f in field_labels], caching=False) - pt.align = 'l' - - for o in objs: - row = [] - for field in fields: - if field in formatters: - row.append(formatters[field](o)) - else: - data = getattr(o, field, None) or '' - row.append(data) - pt.add_row(row) - print pt.get_string(sortby=field_labels[sortby]) - - -def print_dict(d, formatters={}): - pt = prettytable.PrettyTable(['Property', 'Value'], caching=False) - pt.align = 'l' - - for field in d.keys(): - if field in formatters: - pt.add_row([field, formatters[field](d[field])]) - else: - pt.add_row([field, d[field]]) - print pt.get_string(sortby='Property') - - -def find_resource(manager, name_or_id): - """Helper for the _find_* methods.""" - # first try to get entity as integer id - try: - if isinstance(name_or_id, int) or name_or_id.isdigit(): - return manager.get(int(name_or_id)) - except exceptions.NotFound: - pass - - # now try to get entity as uuid - try: - uuid.UUID(str(name_or_id)) - return manager.get(name_or_id) - except (ValueError, exceptions.NotFound): - pass - - # finally try to find entity by name - try: - return manager.find(name=name_or_id) - except exceptions.NotFound: - msg = "No %s with a name or ID of '%s' exists." % \ - (manager.resource_class.__name__.lower(), name_or_id) - raise exceptions.CommandError(msg) - - -def string_to_bool(arg): - return arg.strip().lower() in ('t', 'true', 'yes', '1') - - -def env(*vars, **kwargs): - """Search for the first defined of possibly many env vars - - Returns the first environment variable defined in vars, or - returns the default defined in kwargs. - """ - for v in vars: - value = os.environ.get(v, None) - if value: - return value - return kwargs.get('default', '') - - -def import_versioned_module(version, submodule=None): - module = 'glazierclient.v%s' % version - if submodule: - module = '.'.join((module, submodule)) - return importutils.import_module(module) - - -def exit(msg=''): - if msg: - print >> sys.stderr, msg - sys.exit(1) diff --git a/python-glazierclient/glazierclient/openstack/__init__.py b/python-glazierclient/glazierclient/openstack/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/python-glazierclient/glazierclient/openstack/common/__init__.py b/python-glazierclient/glazierclient/openstack/common/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/python-glazierclient/glazierclient/openstack/common/importutils.py b/python-glazierclient/glazierclient/openstack/common/importutils.py deleted file mode 100644 index 9dec764f..00000000 --- a/python-glazierclient/glazierclient/openstack/common/importutils.py +++ /dev/null @@ -1,67 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Import related utilities and helper functions. -""" - -import sys -import traceback - - -def import_class(import_str): - """Returns a class from a string including module and class""" - mod_str, _sep, class_str = import_str.rpartition('.') - try: - __import__(mod_str) - return getattr(sys.modules[mod_str], class_str) - except (ValueError, AttributeError): - raise ImportError('Class %s cannot be found (%s)' % - (class_str, - traceback.format_exception(*sys.exc_info()))) - - -def import_object(import_str, *args, **kwargs): - """Import a class and return an instance of it.""" - return import_class(import_str)(*args, **kwargs) - - -def import_object_ns(name_space, import_str, *args, **kwargs): - """ - Import a class and return an instance of it, first by trying - to find the class in a default namespace, then failing back to - a full path if not found in the default namespace. - """ - import_value = "%s.%s" % (name_space, import_str) - try: - return import_class(import_value)(*args, **kwargs) - except ImportError: - return import_class(import_str)(*args, **kwargs) - - -def import_module(import_str): - """Import a module.""" - __import__(import_str) - return sys.modules[import_str] - - -def try_import(import_str, default=None): - """Try to import a module and if it fails return default.""" - try: - return import_module(import_str) - except ImportError: - return default diff --git a/python-glazierclient/glazierclient/openstack/common/setup.py b/python-glazierclient/glazierclient/openstack/common/setup.py deleted file mode 100644 index 80a0ecee..00000000 --- a/python-glazierclient/glazierclient/openstack/common/setup.py +++ /dev/null @@ -1,359 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack LLC. -# Copyright 2012-2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Utilities with minimum-depends for use in setup.py -""" - -import email -import os -import re -import subprocess -import sys - -from setuptools.command import sdist - - -def parse_mailmap(mailmap='.mailmap'): - mapping = {} - if os.path.exists(mailmap): - with open(mailmap, 'r') as fp: - for l in fp: - try: - canonical_email, alias = re.match( - r'[^#]*?(<.+>).*(<.+>).*', l).groups() - except AttributeError: - continue - mapping[alias] = canonical_email - return mapping - - -def _parse_git_mailmap(git_dir, mailmap='.mailmap'): - mailmap = os.path.join(os.path.dirname(git_dir), mailmap) - return parse_mailmap(mailmap) - - -def canonicalize_emails(changelog, mapping): - """Takes in a string and an email alias mapping and replaces all - instances of the aliases in the string with their real email. - """ - for alias, email_address in mapping.iteritems(): - changelog = changelog.replace(alias, email_address) - return changelog - - -# Get requirements from the first file that exists -def get_reqs_from_files(requirements_files): - for requirements_file in requirements_files: - if os.path.exists(requirements_file): - with open(requirements_file, 'r') as fil: - return fil.read().split('\n') - return [] - - -def parse_requirements(requirements_files=['requirements.txt', - 'tools/pip-requires']): - requirements = [] - for line in get_reqs_from_files(requirements_files): - # For the requirements list, we need to inject only the portion - # after egg= so that distutils knows the package it's looking for - # such as: - # -e git://github.com/openstack/nova/master#egg=nova - if re.match(r'\s*-e\s+', line): - requirements.append(re.sub(r'\s*-e\s+.*#egg=(.*)$', r'\1', - line)) - # such as: - # http://github.com/openstack/nova/zipball/master#egg=nova - elif re.match(r'\s*https?:', line): - requirements.append(re.sub(r'\s*https?:.*#egg=(.*)$', r'\1', - line)) - # -f lines are for index locations, and don't get used here - elif re.match(r'\s*-f\s+', line): - pass - # argparse is part of the standard library starting with 2.7 - # adding it to the requirements list screws distro installs - elif line == 'argparse' and sys.version_info >= (2, 7): - pass - else: - requirements.append(line) - - return requirements - - -def parse_dependency_links(requirements_files=['requirements.txt', - 'tools/pip-requires']): - dependency_links = [] - # dependency_links inject alternate locations to find packages listed - # in requirements - for line in get_reqs_from_files(requirements_files): - # skip comments and blank lines - if re.match(r'(\s*#)|(\s*$)', line): - continue - # lines with -e or -f need the whole line, minus the flag - if re.match(r'\s*-[ef]\s+', line): - dependency_links.append(re.sub(r'\s*-[ef]\s+', '', line)) - # lines that are only urls can go in unmolested - elif re.match(r'\s*https?:', line): - dependency_links.append(line) - return dependency_links - - -def _run_shell_command(cmd, throw_on_error=False): - if os.name == 'nt': - output = subprocess.Popen(["cmd.exe", "/C", cmd], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - else: - output = subprocess.Popen(["/bin/sh", "-c", cmd], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - out = output.communicate() - if output.returncode and throw_on_error: - raise Exception("%s returned %d" % cmd, output.returncode) - if len(out) == 0: - return None - if len(out[0].strip()) == 0: - return None - return out[0].strip() - - -def _get_git_directory(): - parent_dir = os.path.dirname(__file__) - while True: - git_dir = os.path.join(parent_dir, '.git') - if os.path.exists(git_dir): - return git_dir - parent_dir, child = os.path.split(parent_dir) - if not child: # reached to root dir - return None - - -def write_git_changelog(): - """Write a changelog based on the git changelog.""" - new_changelog = 'ChangeLog' - git_dir = _get_git_directory() - if not os.getenv('SKIP_WRITE_GIT_CHANGELOG'): - if git_dir: - git_log_cmd = 'git --git-dir=%s log --stat' % git_dir - changelog = _run_shell_command(git_log_cmd) - mailmap = _parse_git_mailmap(git_dir) - with open(new_changelog, "w") as changelog_file: - changelog_file.write(canonicalize_emails(changelog, mailmap)) - else: - open(new_changelog, 'w').close() - - -def generate_authors(): - """Create AUTHORS file using git commits.""" - jenkins_email = 'jenkins@review.(openstack|stackforge).org' - old_authors = 'AUTHORS.in' - new_authors = 'AUTHORS' - git_dir = _get_git_directory() - if not os.getenv('SKIP_GENERATE_AUTHORS'): - if git_dir: - # don't include jenkins email address in AUTHORS file - git_log_cmd = ("git --git-dir=" + git_dir + - " log --format='%aN <%aE>' | sort -u | " - "egrep -v '" + jenkins_email + "'") - changelog = _run_shell_command(git_log_cmd) - mailmap = _parse_git_mailmap(git_dir) - with open(new_authors, 'w') as new_authors_fh: - new_authors_fh.write(canonicalize_emails(changelog, mailmap)) - if os.path.exists(old_authors): - with open(old_authors, "r") as old_authors_fh: - new_authors_fh.write('\n' + old_authors_fh.read()) - else: - open(new_authors, 'w').close() - - -_rst_template = """%(heading)s -%(underline)s - -.. automodule:: %(module)s - :members: - :undoc-members: - :show-inheritance: -""" - - -def get_cmdclass(): - """Return dict of commands to run from setup.py.""" - - cmdclass = dict() - - def _find_modules(arg, dirname, files): - for filename in files: - if filename.endswith('.py') and filename != '__init__.py': - arg["%s.%s" % (dirname.replace('/', '.'), - filename[:-3])] = True - - class LocalSDist(sdist.sdist): - """Builds the ChangeLog and Authors files from VC first.""" - - def run(self): - write_git_changelog() - generate_authors() - # sdist.sdist is an old style class, can't use super() - sdist.sdist.run(self) - - cmdclass['sdist'] = LocalSDist - - # If Sphinx is installed on the box running setup.py, - # enable setup.py to build the documentation, otherwise, - # just ignore it - try: - from sphinx.setup_command import BuildDoc - - class LocalBuildDoc(BuildDoc): - - builders = ['html', 'man'] - - def generate_autoindex(self): - print "**Autodocumenting from %s" % os.path.abspath(os.curdir) - modules = {} - option_dict = self.distribution.get_option_dict('build_sphinx') - source_dir = os.path.join(option_dict['source_dir'][1], 'api') - if not os.path.exists(source_dir): - os.makedirs(source_dir) - for pkg in self.distribution.packages: - if '.' not in pkg: - os.path.walk(pkg, _find_modules, modules) - module_list = modules.keys() - module_list.sort() - autoindex_filename = os.path.join(source_dir, 'autoindex.rst') - with open(autoindex_filename, 'w') as autoindex: - autoindex.write(""".. toctree:: - :maxdepth: 1 - -""") - for module in module_list: - output_filename = os.path.join(source_dir, - "%s.rst" % module) - heading = "The :mod:`%s` Module" % module - underline = "=" * len(heading) - values = dict(module=module, heading=heading, - underline=underline) - - print "Generating %s" % output_filename - with open(output_filename, 'w') as output_file: - output_file.write(_rst_template % values) - autoindex.write(" %s.rst\n" % module) - - def run(self): - if not os.getenv('SPHINX_DEBUG'): - self.generate_autoindex() - - for builder in self.builders: - self.builder = builder - self.finalize_options() - self.project = self.distribution.get_name() - self.version = self.distribution.get_version() - self.release = self.distribution.get_version() - BuildDoc.run(self) - - class LocalBuildLatex(LocalBuildDoc): - builders = ['latex'] - - cmdclass['build_sphinx'] = LocalBuildDoc - cmdclass['build_sphinx_latex'] = LocalBuildLatex - except ImportError: - pass - - return cmdclass - - -def _get_revno(git_dir): - """Return the number of commits since the most recent tag. - - We use git-describe to find this out, but if there are no - tags then we fall back to counting commits since the beginning - of time. - """ - describe = _run_shell_command( - "git --git-dir=%s describe --always" % git_dir) - if "-" in describe: - return describe.rsplit("-", 2)[-2] - - # no tags found - revlist = _run_shell_command( - "git --git-dir=%s rev-list --abbrev-commit HEAD" % git_dir) - return len(revlist.splitlines()) - - -def _get_version_from_git(pre_version): - """Return a version which is equal to the tag that's on the current - revision if there is one, or tag plus number of additional revisions - if the current revision has no tag.""" - - git_dir = _get_git_directory() - if git_dir: - if pre_version: - try: - return _run_shell_command( - "git --git-dir=" + git_dir + " describe --exact-match", - throw_on_error=True).replace('-', '.') - except Exception: - sha = _run_shell_command( - "git --git-dir=" + git_dir + " log -n1 --pretty=format:%h") - return "%s.a%s.g%s" % (pre_version, _get_revno(git_dir), sha) - else: - return _run_shell_command( - "git --git-dir=" + git_dir + " describe --always").replace( - '-', '.') - return None - - -def _get_version_from_pkg_info(package_name): - """Get the version from PKG-INFO file if we can.""" - try: - pkg_info_file = open('PKG-INFO', 'r') - except (IOError, OSError): - return None - try: - pkg_info = email.message_from_file(pkg_info_file) - except email.MessageError: - return None - # Check to make sure we're in our own dir - if pkg_info.get('Name', None) != package_name: - return None - return pkg_info.get('Version', None) - - -def get_version(package_name, pre_version=None): - """Get the version of the project. First, try getting it from PKG-INFO, if - it exists. If it does, that means we're in a distribution tarball or that - install has happened. Otherwise, if there is no PKG-INFO file, pull the - version from git. - - We do not support setup.py version sanity in git archive tarballs, nor do - we support packagers directly sucking our git repo into theirs. We expect - that a source tarball be made from our git repo - or that if someone wants - to make a source tarball from a fork of our repo with additional tags in it - that they understand and desire the results of doing that. - """ - version = os.environ.get("OSLO_PACKAGE_VERSION", None) - if version: - return version - version = _get_version_from_pkg_info(package_name) - if version: - return version - version = _get_version_from_git(pre_version) - if version: - return version - raise Exception("Versioning for this project requires either an sdist" - " tarball, or access to an upstream git repository.") diff --git a/python-glazierclient/glazierclient/openstack/common/version.py b/python-glazierclient/glazierclient/openstack/common/version.py deleted file mode 100644 index d0cad115..00000000 --- a/python-glazierclient/glazierclient/openstack/common/version.py +++ /dev/null @@ -1,94 +0,0 @@ - -# Copyright 2012 OpenStack LLC -# Copyright 2012-2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Utilities for consuming the version from pkg_resources. -""" - -import pkg_resources - - -class VersionInfo(object): - - def __init__(self, package): - """Object that understands versioning for a package - :param package: name of the python package, such as glance, or - python-glanceclient - """ - self.package = package - self.release = None - self.version = None - self._cached_version = None - - def __str__(self): - """Make the VersionInfo object behave like a string.""" - return self.version_string() - - def __repr__(self): - """Include the name.""" - return "VersionInfo(%s:%s)" % (self.package, self.version_string()) - - def _get_version_from_pkg_resources(self): - """Get the version of the package from the pkg_resources record - associated with the package.""" - try: - requirement = pkg_resources.Requirement.parse(self.package) - provider = pkg_resources.get_provider(requirement) - return provider.version - except pkg_resources.DistributionNotFound: - # The most likely cause for this is running tests in a tree - # produced from a tarball where the package itself has not been - # installed into anything. Revert to setup-time logic. - from glazierclient.openstack.common import setup - return setup.get_version(self.package) - - def release_string(self): - """Return the full version of the package including suffixes indicating - VCS status. - """ - if self.release is None: - self.release = self._get_version_from_pkg_resources() - - return self.release - - def version_string(self): - """Return the short version minus any alpha/beta tags.""" - if self.version is None: - parts = [] - for part in self.release_string().split('.'): - if part[0].isdigit(): - parts.append(part) - else: - break - self.version = ".".join(parts) - - return self.version - - # Compatibility functions - canonical_version_string = version_string - version_string_with_vcs = release_string - - def cached_version_string(self, prefix=""): - """Generate an object which will expand in a string context to - the results of version_string(). We do this so that don't - call into pkg_resources every time we start up a program when - passing version information into the CONF constructor, but - rather only do the calculation when and if a version is requested - """ - if not self._cached_version: - self._cached_version = "%s%s" % (prefix, - self.version_string()) - return self._cached_version diff --git a/python-glazierclient/glazierclient/shell.py b/python-glazierclient/glazierclient/shell.py deleted file mode 100644 index bbadc89d..00000000 --- a/python-glazierclient/glazierclient/shell.py +++ /dev/null @@ -1,314 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Command-line interface to the Glazier Project. -""" - -import argparse -import logging -import sys - -import httplib2 -from keystoneclient.v2_0 import client as ksclient -from glazierclient import client as glazierclient -from glazierclient.common import utils, exceptions - - -logger = logging.getLogger(__name__) - - -class GlazierShell(object): - def get_base_parser(self): - parser = argparse.ArgumentParser( - prog='glazier', - description=__doc__.strip(), - epilog='See glazier help COMMAND" ' - 'for help on a specific command.', - add_help=False, - formatter_class=HelpFormatter, - ) - - # Global arguments - parser.add_argument('-h', '--help', - action='store_true', - help=argparse.SUPPRESS,) - - parser.add_argument('-d', '--debug', - default=bool(utils.env('GLAZIERCLIENT_DEBUG')), - action='store_true', - help='Defaults to env[GLAZIERCLIENT_DEBUG]') - - parser.add_argument('-v', '--verbose', - default=False, action="store_true", - help="Print more verbose output") - - parser.add_argument('-k', '--insecure', - default=False, - action='store_true', - help="Explicitly allow glazierclient to perform " - "\"insecure\" SSL (https) requests. " - "The server's certificate will " - "not be verified against any certificate " - "authorities. This option should be used " - "with caution.") - - parser.add_argument('--cert-file', - help='Path of certificate file to use in SSL ' - 'connection. This file can optionally be ' - 'prepended with the private key.') - - parser.add_argument('--key-file', - help='Path of client key to use in SSL connection.' - ' This option is not necessary if your ' - 'key is prepended to your cert file.') - - parser.add_argument('--ca-file', - help='Path of CA SSL certificate(s) used to verify' - ' the remote server certificate. Without ' - 'this option glance looks for the default ' - 'system CA certificates.') - - parser.add_argument('--timeout', - default=600, - help='Number of seconds to wait for a response') - - parser.add_argument('--os-username', - default=utils.env('OS_USERNAME'), - help='Defaults to env[OS_USERNAME]') - - parser.add_argument('--os-password', - default=utils.env('OS_PASSWORD'), - help='Defaults to env[OS_PASSWORD]') - - parser.add_argument('--os-tenant-id', - default=utils.env('OS_TENANT_ID'), - help='Defaults to env[OS_TENANT_ID]') - - parser.add_argument('--os-tenant-name', - default=utils.env('OS_TENANT_NAME'), - help='Defaults to env[OS_TENANT_NAME]') - - parser.add_argument('--os-auth-url', - default=utils.env('OS_AUTH_URL'), - help='Defaults to env[OS_AUTH_URL]') - - parser.add_argument('--os-region-name', - default=utils.env('OS_REGION_NAME'), - help='Defaults to env[OS_REGION_NAME]') - - parser.add_argument('--os-auth-token', - default=utils.env('OS_AUTH_TOKEN'), - help='Defaults to env[OS_AUTH_TOKEN]') - - parser.add_argument('--glazier-url', - default=utils.env('GLAZIER_URL'), - help='Defaults to env[GLAZIER_URL]') - - parser.add_argument('--glazier-api-version', - default=utils.env( - 'GLAZIER_API_VERSION', default='1'), - help='Defaults to env[GLAZIER_API_VERSION] ' - 'or 1') - - parser.add_argument('--os-service-type', - default=utils.env('OS_SERVICE_TYPE'), - help='Defaults to env[OS_SERVICE_TYPE]') - - parser.add_argument('--os-endpoint-type', - default=utils.env('OS_ENDPOINT_TYPE'), - help='Defaults to env[OS_ENDPOINT_TYPE]') - - return parser - - def get_subcommand_parser(self, version): - parser = self.get_base_parser() - - self.subcommands = {} - subparsers = parser.add_subparsers(metavar='<subcommand>') - submodule = utils.import_versioned_module(version, 'shell') - self._find_actions(subparsers, submodule) - self._find_actions(subparsers, self) - - return parser - - def _find_actions(self, subparsers, actions_module): - for attr in (a for a in dir(actions_module) if a.startswith('do_')): - # I prefer to be hypen-separated instead of underscores. - command = attr[3:].replace('_', '-') - callback = getattr(actions_module, attr) - desc = callback.__doc__ or '' - help = desc.strip().split('\n')[0] - arguments = getattr(callback, 'arguments', []) - - subparser = subparsers.add_parser(command, help=help, - description=desc, - add_help=False, - formatter_class=HelpFormatter) - subparser.add_argument('-h', '--help', action='help', - help=argparse.SUPPRESS) - self.subcommands[command] = subparser - for (args, kwargs) in arguments: - subparser.add_argument(*args, **kwargs) - subparser.set_defaults(func=callback) - - def _get_ksclient(self, **kwargs): - """Get an endpoint and auth token from Keystone. - - :param username: name of user - :param password: user's password - :param tenant_id: unique identifier of tenant - :param tenant_name: name of tenant - :param auth_url: endpoint to authenticate against - """ - return ksclient.Client(username=kwargs.get('username'), - password=kwargs.get('password'), - tenant_id=kwargs.get('tenant_id'), - tenant_name=kwargs.get('tenant_name'), - auth_url=kwargs.get('auth_url'), - insecure=kwargs.get('insecure')) - - def _get_endpoint(self, client, **kwargs): - """Get an endpoint using the provided keystone client.""" - return client.service_catalog.url_for( - service_type=kwargs.get('service_type') or 'metering', - endpoint_type=kwargs.get('endpoint_type') or 'publicURL') - - def _setup_debugging(self, debug): - if debug: - logging.basicConfig( - format="%(levelname)s (%(module)s:%(lineno)d) %(message)s", - level=logging.DEBUG) - - httplib2.debuglevel = 1 - else: - logging.basicConfig( - format="%(levelname)s %(message)s", - level=logging.INFO) - - def main(self, argv): - # Parse args once to find version - parser = self.get_base_parser() - (options, args) = parser.parse_known_args(argv) - self._setup_debugging(options.debug) - - # build available subcommands based on version - api_version = options.glazier_api_version - subcommand_parser = self.get_subcommand_parser(api_version) - self.parser = subcommand_parser - - # Handle top-level --help/-h before attempting to parse - # a command off the command line - if options.help or not argv: - self.do_help(options) - return 0 - - # Parse args again and call whatever callback was selected - args = subcommand_parser.parse_args(argv) - - # Short-circuit and deal with help command right away. - if args.func == self.do_help: - self.do_help(args) - return 0 - - if args.os_auth_token and args.glazier_url: - token = args.os_auth_token - endpoint = args.glazier_url - else: - if not args.os_username: - raise exceptions.CommandError("You must provide a username " - "via either --os-username " - "or via env[OS_USERNAME]") - - if not args.os_password: - raise exceptions.CommandError("You must provide a password " - "via either --os-password " - "or via env[OS_PASSWORD]") - - if not (args.os_tenant_id or args.os_tenant_name): - raise exceptions.CommandError("You must provide a tenant_id " - "via either --os-tenant-id " - "or via env[OS_TENANT_ID]") - - if not args.os_auth_url: - raise exceptions.CommandError("You must provide an auth url " - "via either --os-auth-url or " - "via env[OS_AUTH_URL]") - kwargs = { - 'username': args.os_username, - 'password': args.os_password, - 'tenant_id': args.os_tenant_id, - 'tenant_name': args.os_tenant_name, - 'auth_url': args.os_auth_url, - 'service_type': args.os_service_type, - 'endpoint_type': args.os_endpoint_type, - 'insecure': args.insecure - } - _ksclient = self._get_ksclient(**kwargs) - token = args.os_auth_token or _ksclient.auth_token - - url = args.glazier_url - endpoint = url or self._get_endpoint(_ksclient, **kwargs) - - kwargs = { - 'token': token, - 'insecure': args.insecure, - 'timeout': args.timeout, - 'ca_file': args.ca_file, - 'cert_file': args.cert_file, - 'key_file': args.key_file, - } - - client = glazierclient.Client(api_version, endpoint, **kwargs) - - try: - args.func(client, args) - except exceptions.Unauthorized: - msg = "Invalid OpenStack Identity credentials." - raise exceptions.CommandError(msg) - - @utils.arg('command', metavar='<subcommand>', nargs='?', - help='Display help for <subcommand>') - def do_help(self, args): - """ - Display help about this program or one of its subcommands. - """ - if getattr(args, 'command', None): - if args.command in self.subcommands: - self.subcommands[args.command].print_help() - else: - msg = "'%s' is not a valid subcommand" - raise exceptions.CommandError(msg % args.command) - else: - self.parser.print_help() - - -class HelpFormatter(argparse.HelpFormatter): - def start_section(self, heading): - # Title-case the headings - heading = '%s%s' % (heading[0].upper(), heading[1:]) - super(HelpFormatter, self).start_section(heading) - - -def main(): - try: - GlazierShell().main(sys.argv[1:]) - - except Exception, e: - print >> sys.stderr, e - sys.exit(1) - - -if __name__ == "__main__": - main() diff --git a/python-glazierclient/glazierclient/v1/__init__.py b/python-glazierclient/glazierclient/v1/__init__.py deleted file mode 100644 index dbe3f042..00000000 --- a/python-glazierclient/glazierclient/v1/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from glazierclient.v1.client import Client diff --git a/python-glazierclient/glazierclient/v1/client.py b/python-glazierclient/glazierclient/v1/client.py deleted file mode 100644 index 960691ce..00000000 --- a/python-glazierclient/glazierclient/v1/client.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from glazierclient.common import http -from glazierclient.v1 import environments, sessions, services - - -class Client(http.HTTPClient): - """Client for the Glazier v1 API. - - :param string endpoint: A user-supplied endpoint URL for the service. - :param string token: Token for authentication. - :param integer timeout: Allows customization of the timeout for client - http requests. (optional) - """ - - def __init__(self, *args, **kwargs): - """ Initialize a new client for the Glazier v1 API. """ - super(Client, self).__init__(*args, **kwargs) - self.environments = environments.EnvironmentManager(self) - self.sessions = sessions.SessionManager(self) - self.activeDirectories = services.ActiveDirectoryManager(self) - self.webServers = services.WebServerManager(self) diff --git a/python-glazierclient/glazierclient/v1/environments.py b/python-glazierclient/glazierclient/v1/environments.py deleted file mode 100644 index 43705c01..00000000 --- a/python-glazierclient/glazierclient/v1/environments.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from glazierclient.common import base - - -class Environment(base.Resource): - def __repr__(self): - return "<Environment %s>" % self._info - - def data(self, **kwargs): - return self.manager.data(self, **kwargs) - - -class EnvironmentManager(base.Manager): - resource_class = Environment - - def list(self): - return self._list('environments', 'environments') - - def create(self, name): - return self._create('environments', {'name': name}) - - def update(self, environment_id, name): - return self._update('environments/{id}'.format(id=environment_id), - {'name': name}) - - def delete(self, environment_id): - return self._delete('environments/{id}'.format(id=environment_id)) - - def get(self, environment_id): - return self._get("environments/{id}".format(id=environment_id)) diff --git a/python-glazierclient/glazierclient/v1/services.py b/python-glazierclient/glazierclient/v1/services.py deleted file mode 100644 index 39874a68..00000000 --- a/python-glazierclient/glazierclient/v1/services.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from glazierclient.common import base - - -class ActiveDirectory(base.Resource): - def __repr__(self): - return '<ActiveDirectory %s>' % self._info - - def data(self, **kwargs): - return self.manager.data(self, **kwargs) - - -class ActiveDirectoryManager(base.Manager): - resource_class = ActiveDirectory - - def list(self, environment_id, session_id=None): - if session_id: - headers = {'X-Configuration-Session': session_id} - else: - headers = {} - - return self._list('environments/{id}/activeDirectories'. - format(id=environment_id), - 'activeDirectories', - headers=headers) - - def create(self, environment_id, session_id, active_directory): - headers = {'X-Configuration-Session': session_id} - - return self._create('environments/{id}/activeDirectories'. - format(id=environment_id), - active_directory, - headers=headers) - - def delete(self, environment_id, session_id, service_id): - headers = {'X-Configuration-Session': session_id} - path = 'environments/{id}/activeDirectories/{active_directory_id}' - path = path.format(id=environment_id, active_directory_id=service_id) - - return self._delete(path, headers=headers) - - -class WebServer(base.Resource): - def __repr__(self): - return '<WebServer %s>' % self._info - - def data(self, **kwargs): - return self.manager.data(self, **kwargs) - - -class WebServerManager(base.Manager): - resource_class = WebServer - - def list(self, environment_id, session_id=None): - if session_id: - headers = {'X-Configuration-Session': session_id} - else: - headers = {} - - return self._list('environments/{id}/webServers'. - format(id=environment_id), - 'webServers', - headers=headers) - - def create(self, environment_id, session_id, web_server): - headers = {'X-Configuration-Session': session_id} - - return self._create('environments/{id}/webServers'. - format(id=environment_id), - web_server, - headers=headers) - - def delete(self, environment_id, session_id, service_id): - headers = {'X-Configuration-Session': session_id} - - return self._delete('environments/{id}/webServers/{web_server_id}' - .format(id=environment_id, - web_server_id=service_id), - headers=headers) diff --git a/python-glazierclient/glazierclient/v1/sessions.py b/python-glazierclient/glazierclient/v1/sessions.py deleted file mode 100644 index 2efcf7f3..00000000 --- a/python-glazierclient/glazierclient/v1/sessions.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from glazierclient.common import base - - -class Session(base.Resource): - def __repr__(self): - return '<Session %s>' % self._info - - def data(self, **kwargs): - return self.manager.data(self, **kwargs) - - -class Status(base.Resource): - def __repr__(self): - return '<Status %s>' % self._info - - def data(self, **kwargs): - return self.manager.data(self, **kwargs) - - -class SessionManager(base.Manager): - resource_class = Session - - def list(self, environment_id): - return self._list('environments/{id}/sessions'. - format(id=environment_id), 'sessions') - - def get(self, environment_id, session_id): - return self._get('environments/{id}/sessions/{session_id}'. - format(id=environment_id, session_id=session_id)) - - def configure(self, environment_id): - return self._create('environments/{id}/configure'. - format(id=environment_id), None) - - def deploy(self, environment_id, session_id): - path = 'environments/{id}/sessions/{session_id}/deploy' - self.api.json_request('POST', - path.format(id=environment_id, - session_id=session_id)) - - def reports(self, environment_id, session_id, service_id=None): - path = 'environments/{id}/sessions/{session_id}/reports' - path = path.format(id=environment_id, session_id=session_id) - if service_id: - path += '?service_id={0}'.format(service_id) - - resp, body = self.api.json_request('GET', path) - - data = body.get('reports', []) - return [Status(self, res, loaded=True) for res in data if res] - - def delete(self, environment_id, session_id): - return self._delete("environments/{id}/sessions/{session_id}". - format(id=environment_id, session_id=session_id)) diff --git a/python-glazierclient/glazierclient/v1/shell.py b/python-glazierclient/glazierclient/v1/shell.py deleted file mode 100644 index 8f4a619c..00000000 --- a/python-glazierclient/glazierclient/v1/shell.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from glazierclient.common import utils - - -def do_environment_list(cc, args={}): - """List the environments""" - environments = cc.environments.list() - field_labels = ['ID', 'Name', 'Created', 'Updated'] - fields = ['id', 'name', 'created', 'updated'] - utils.print_list(environments, fields, field_labels, sortby=0) diff --git a/python-glazierclient/glazierclient/version.py b/python-glazierclient/glazierclient/version.py deleted file mode 100644 index 8c38a387..00000000 --- a/python-glazierclient/glazierclient/version.py +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -from glazierclient.openstack.common import version as common_version - -version_info = common_version.VersionInfo('python-glazierclient') diff --git a/python-glazierclient/openstack-common.conf b/python-glazierclient/openstack-common.conf deleted file mode 100644 index eefdecce..00000000 --- a/python-glazierclient/openstack-common.conf +++ /dev/null @@ -1,7 +0,0 @@ -[DEFAULT] - -# The list of modules to copy from openstack-common -modules=setup,importutils,version - -# The base module to hold the copy of openstack.common -base=glazierclient diff --git a/python-glazierclient/run_tests.sh b/python-glazierclient/run_tests.sh deleted file mode 100755 index 1e790721..00000000 --- a/python-glazierclient/run_tests.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash - -function usage { - echo "Usage: $0 [OPTION]..." - echo "Run python-glazierclient's test suite(s)" - echo "" - echo " -p, --pep8 Just run pep8" - echo " -h, --help Print this usage message" - echo "" - echo "This script is deprecated and currently retained for compatibility." - echo 'You can run the full test suite for multiple environments by running "tox".' - echo 'You can run tests for only python 2.7 by running "tox -e py27", or run only' - echo 'the pep8 tests with "tox -e pep8".' - exit -} - -command -v tox > /dev/null 2>&1 -if [ $? -ne 0 ]; then - echo 'This script requires "tox" to run.' - echo 'You can install it with "pip install tox".' - exit 1; -fi - -just_pep8=0 - -function process_option { - case "$1" in - -h|--help) usage;; - -p|--pep8) let just_pep8=1;; - esac -} - -for arg in "$@"; do - process_option $arg -done - -if [ $just_pep8 -eq 1 ]; then - tox -e pep8 - exit -fi - -tox -e py27 $toxargs 2>&1 | tee run_tests.err.log || exit -if [ ${PIPESTATUS[0]} -ne 0 ]; then - exit ${PIPESTATUS[0]} -fi - -if [ -z "$toxargs" ]; then - tox -e pep8 -fi diff --git a/python-glazierclient/setup.cfg b/python-glazierclient/setup.cfg deleted file mode 100644 index 78493eca..00000000 --- a/python-glazierclient/setup.cfg +++ /dev/null @@ -1,15 +0,0 @@ -[nosetests] -cover-package = glazierclient -cover-html = true -cover-erase = true -cover-inclusive = true -verbosity=2 -detailed-errors=1 - -[build_sphinx] -source-dir = doc/source -build-dir = doc/build -all_files = 1 - -[upload_sphinx] -upload-dir = doc/build/html diff --git a/python-glazierclient/setup.py b/python-glazierclient/setup.py deleted file mode 100644 index 56cbead2..00000000 --- a/python-glazierclient/setup.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import setuptools - -from glazierclient.openstack.common import setup - -project = 'python-glazierclient' - - -setuptools.setup( - name=project, - version=setup.get_version(project, '2013.1'), - author='Mirantis, Inc.', - author_email='smelikyan@mirantis.com', - description="Client library for Glazier Project", - license='Apache', - url='http://glazier.mirantis.com/', - packages=setuptools.find_packages(exclude=['tests', 'tests.*']), - include_package_data=True, - install_requires=setup.parse_requirements(), - test_suite="nose.collector", - cmdclass=setup.get_cmdclass(), - classifiers=[ - 'Development Status :: 4 - Beta', - 'Environment :: Console', - 'Intended Audience :: Developers', - 'Intended Audience :: Information Technology', - 'License :: OSI Approved :: Apache Software License', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - ], - entry_points={ - 'console_scripts': ['glazier = glazierclient.shell:main'] - }, - dependency_links=setup.parse_dependency_links(), - tests_require=setup.parse_requirements(['tools/test-requires']), - setup_requires=['setuptools-git>=0.4'], -) diff --git a/python-glazierclient/tests/__init__.py b/python-glazierclient/tests/__init__.py deleted file mode 100644 index 207fa154..00000000 --- a/python-glazierclient/tests/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. \ No newline at end of file diff --git a/python-glazierclient/tests/glazierclient/__init__.py b/python-glazierclient/tests/glazierclient/__init__.py deleted file mode 100644 index 207fa154..00000000 --- a/python-glazierclient/tests/glazierclient/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. \ No newline at end of file diff --git a/python-glazierclient/tests/glazierclient/test_client_with_fake_http.py b/python-glazierclient/tests/glazierclient/test_client_with_fake_http.py deleted file mode 100644 index 7c7eaad1..00000000 --- a/python-glazierclient/tests/glazierclient/test_client_with_fake_http.py +++ /dev/null @@ -1,208 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import unittest -import logging -from httpretty import HTTPretty, httprettified -from glazierclient.client import Client - - -LOG = logging.getLogger('Unit tests') - - -class UnitTestsForClassesAndFunctions(unittest.TestCase): - - @httprettified - def test_client_env_list_with_empty_list(self): - HTTPretty.register_uri(HTTPretty.GET, - "http://no-resolved-host:8001/environments", - body='{"environments": []}', - adding_headers={ - 'Content-Type': 'application/json',}) - endpoint = 'http://no-resolved-host:8001' - test_client = Client('1', endpoint=endpoint, token='1', timeout=10) - - result = test_client.environments.list() - assert result == [] - - @httprettified - def test_client_env_list_with_elements(self): - body = ('{"environments":[' - '{"id": "0ce373a477f211e187a55404a662f968",' - '"name": "dc1",' - '"created": "2010-11-30T03:23:42Z",' - '"updated": "2010-11-30T03:23:44Z",' - '"tenant-id": "0849006f7ce94961b3aab4e46d6f229a"},' - '{"id": "0ce373a477f211e187a55404a662f961",' - '"name": "dc2",' - '"created": "2010-11-30T03:23:42Z",' - '"updated": "2010-11-30T03:23:44Z",' - '"tenant-id": "0849006f7ce94961b3aab4e4626f229a"}' - ']}') - HTTPretty.register_uri(HTTPretty.GET, - "http://no-resolved-host:8001/environments", - body=body, - adding_headers={ - 'Content-Type': 'application/json',}) - endpoint = 'http://no-resolved-host:8001' - test_client = Client('1', endpoint=endpoint, token='1', timeout=10) - - result = test_client.environments.list() - assert result[0].name == 'dc1' - assert result[-1].name == 'dc2' - - @httprettified - def test_client_env_create(self): - body = ('{"id": "0ce373a477f211e187a55404a662f968",' - '"name": "test",' - '"created": "2010-11-30T03:23:42Z",' - '"updated": "2010-11-30T03:23:44Z",' - '"tenant-id": "0849006f7ce94961b3aab4e46d6f229a"}' - ) - HTTPretty.register_uri(HTTPretty.POST, - "http://no-resolved-host:8001/environments", - body=body, - adding_headers={ - 'Content-Type': 'application/json',}) - endpoint = 'http://no-resolved-host:8001' - test_client = Client('1', endpoint=endpoint, token='1', timeout=10) - - result = test_client.environments.create('test') - assert result.name == 'test' - - @httprettified - def test_client_ad_list(self): - body = ('{"activeDirectories": [{' - '"id": "1",' - '"name": "dc1",' - '"created": "2010-11-30T03:23:42Z",' - '"updated": "2010-11-30T03:23:44Z",' - '"configuration": "standalone",' - '"units": [{' - '"id": "0ce373a477f211e187a55404a662f961",' - '"type": "master",' - '"location": "test"}]}]}') - url = ("http://no-resolved-host:8001/environments" - "/1/activeDirectories") - HTTPretty.register_uri(HTTPretty.GET, url, - body=body, - adding_headers={ - 'Content-Type': 'application/json',}) - endpoint = 'http://no-resolved-host:8001' - test_client = Client('1', endpoint=endpoint, token='1', timeout=10) - - result = test_client.activeDirectories.list('1', 'test') - assert result[0].name == 'dc1' - - @httprettified - def test_client_ad_create(self): - body = ('{' - '"id": "1",' - '"name": "ad1",' - '"created": "2010-11-30T03:23:42Z",' - '"updated": "2010-11-30T03:23:44Z",' - '"configuration": "standalone",' - '"units": [{' - '"id": "0ce373a477f211e187a55404a662f961",' - '"type": "master",' - '"location": "test"}]}') - url = ("http://no-resolved-host:8001/environments" - "/1/activeDirectories") - HTTPretty.register_uri(HTTPretty.POST, url, - body=body, - adding_headers={ - 'Content-Type': 'application/json',}) - endpoint = 'http://no-resolved-host:8001' - test_client = Client('1', endpoint=endpoint, token='1', timeout=10) - - result = test_client.activeDirectories.create('1', 'test', 'ad1') - assert result.name == 'ad1' - - @httprettified - def test_client_ad_list_without_elements(self): - body = ('{"activeDirectories": []}') - url = ("http://no-resolved-host:8001/environments" - "/1/activeDirectories") - HTTPretty.register_uri(HTTPretty.GET, url, - body=body, - adding_headers={ - 'Content-Type': 'application/json',}) - endpoint = 'http://no-resolved-host:8001' - test_client = Client('1', endpoint=endpoint, token='1', timeout=10) - - result = test_client.activeDirectories.list('1', 'test') - assert result == [] - - @httprettified - def test_client_iis_list(self): - body = ('{"webServers": [{' - '"id": "1",' - '"name": "iis11",' - '"created": "2010-11-30T03:23:42Z",' - '"updated": "2010-11-30T03:23:44Z",' - '"domain": "acme",' - '"units": [{' - '"id": "0ce373a477f211e187a55404a662f961",' - '"endpoint": {"host": "1.1.1.1"},' - '"location": "test"}]}]}') - url = ("http://no-resolved-host:8001/environments" - "/1/webServers") - HTTPretty.register_uri(HTTPretty.GET, url, - body=body, - adding_headers={ - 'Content-Type': 'application/json',}) - endpoint = 'http://no-resolved-host:8001' - test_client = Client('1', endpoint=endpoint, token='1', timeout=10) - - result = test_client.webServers.list('1', 'test') - assert result[0].name == 'iis11' - - @httprettified - def test_client_iis_create(self): - body = ('{' - '"id": "1",' - '"name": "iis12",' - '"created": "2010-11-30T03:23:42Z",' - '"updated": "2010-11-30T03:23:44Z",' - '"domain": "acme",' - '"units": [{' - '"id": "0ce373a477f211e187a55404a662f961",' - '"endpoint": {"host": "1.1.1.1"},' - '"location": "test"}]}') - url = ("http://no-resolved-host:8001/environments" - "/1/webServers") - HTTPretty.register_uri(HTTPretty.POST, url, - body=body, - adding_headers={ - 'Content-Type': 'application/json',}) - endpoint = 'http://no-resolved-host:8001' - test_client = Client('1', endpoint=endpoint, token='1', timeout=10) - - result = test_client.webServers.create('1', 'test', 'iis12') - assert result.name == 'iis12' - - @httprettified - def test_client_iis_list_without_elements(self): - body = ('{"webServers": []}') - url = ("http://no-resolved-host:8001/environments" - "/1/webServers") - HTTPretty.register_uri(HTTPretty.GET, url, - body=body, - adding_headers={ - 'Content-Type': 'application/json',}) - endpoint = 'http://no-resolved-host:8001' - test_client = Client('1', endpoint=endpoint, token='1', timeout=10) - - result = test_client.webServers.list('1', 'test') - assert result == [] diff --git a/python-glazierclient/tests/glazierclient/test_methods.py b/python-glazierclient/tests/glazierclient/test_methods.py deleted file mode 100644 index 31b9751b..00000000 --- a/python-glazierclient/tests/glazierclient/test_methods.py +++ /dev/null @@ -1,481 +0,0 @@ -# Copyright (c) 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import unittest -import logging -from mock import MagicMock - -from glazierclient.client import Client -import glazierclient.v1.environments as environments -import glazierclient.v1.services as services -import glazierclient.v1.sessions as sessions - -def my_mock(*a, **b): - return [a, b] - -LOG = logging.getLogger('Unit tests') -api = MagicMock(json_request=my_mock) - - -class UnitTestsForClassesAndFunctions(unittest.TestCase): - - def test_create_client_instance(self): - - endpoint = 'http://no-resolved-host:8001' - test_client = Client('1', endpoint=endpoint, token='1', timeout=10) - - assert test_client.environments is not None - assert test_client.sessions is not None - assert test_client.activeDirectories is not None - assert test_client.webServers is not None - - def test_env_manager_list(self): - manager = environments.EnvironmentManager(api) - result = manager.list() - assert result == [] - - def test_env_manager_create(self): - manager = environments.EnvironmentManager(api) - result = manager.create('test') - assert result.body == {'name': 'test'} - - def test_env_manager_create_with_named_parameters(self): - manager = environments.EnvironmentManager(api) - result = manager.create(name='test') - assert result.body == {'name': 'test'} - - def test_env_manager_create_negative_without_parameters(self): - result = 'Exception' - manager = environments.EnvironmentManager(api) - try: - result = manager.create() - except TypeError: - pass - assert result is 'Exception' - - def test_env_manager_delete(self): - manager = environments.EnvironmentManager(api) - result = manager.delete('test') - assert result is None - - def test_env_manager_delete_with_named_parameters(self): - manager = environments.EnvironmentManager(api) - result = manager.delete(environment_id='1') - assert result is None - - def test_env_manager_delete_negative_without_parameters(self): - result = 'Exception' - manager = environments.EnvironmentManager(api) - try: - result = manager.delete() - except TypeError: - pass - assert result is 'Exception' - - def test_env_manager_update(self): - manager = environments.EnvironmentManager(api) - result = manager.update('1', 'test') - assert result.body == {'name': 'test'} - - def test_env_manager_update_with_named_parameters(self): - manager = environments.EnvironmentManager(api) - result = manager.update(environment_id='1', - name='test') - assert result.body == {'name': 'test'} - - def test_env_manager_update_negative_with_one_parameter(self): - result = 'Exception' - manager = environments.EnvironmentManager(api) - try: - result = manager.update('test') - except TypeError: - pass - assert result is 'Exception' - - def test_env_manager_update_negative_without_parameters(self): - result = 'Exception' - manager = environments.EnvironmentManager(api) - try: - result = manager.update() - except TypeError: - pass - assert result is 'Exception' - - def test_env_manager_get(self): - manager = environments.EnvironmentManager(api) - result = manager.get('test') - ## WTF? - assert result.manager is not None - - def test_env(self): - environment = environments.Environment(api, api) - assert environment.data() is not None - - def test_ad_manager_list_with_one_parameter(self): - manager = services.ActiveDirectoryManager(api) - result = manager.list('datacenter1') - assert result == [] - - def test_ad_manager_list_with_all_parameters(self): - manager = services.ActiveDirectoryManager(api) - result = manager.list('test', '1') - assert result == [] - - def test_ad_manager_list_with_named_parameters(self): - manager = services.ActiveDirectoryManager(api) - result = manager.list(environment_id='test', session_id='1') - assert result == [] - - def test_ad_manager_list_with_named_parameter(self): - manager = services.ActiveDirectoryManager(api) - result = manager.list(environment_id='test') - assert result == [] - - def test_ad_manager_list_negative_without_parameters(self): - result = 'Exception' - manager = services.ActiveDirectoryManager(api) - try: - result = manager.list() - except TypeError: - pass - assert result is 'Exception' - - def test_ad_manager_create(self): - manager = services.ActiveDirectoryManager(api) - result = manager.create('datacenter1', 'session1', 'test') - assert result.headers == {'X-Configuration-Session': 'session1'} - assert result.body == 'test' - - def test_ad_manager_create_with_named_parameters(self): - manager = services.ActiveDirectoryManager(api) - result = manager.create(environment_id='datacenter1', - session_id='session2', - active_directory='test2') - assert result.headers == {'X-Configuration-Session': 'session2'} - assert result.body == 'test2' - - def test_ad_manager_create_negative_with_two_parameters(self): - result = 'Exception' - manager = services.ActiveDirectoryManager(api) - try: - result = manager.create('datacenter1', 'session1') - except TypeError: - pass - assert result is 'Exception' - - def test_ad_manager_create_negative_with_one_parameter(self): - result = 'Exception' - manager = services.ActiveDirectoryManager(api) - try: - result = manager.create('datacenter1') - except TypeError: - pass - assert result is 'Exception' - - def test_ad_manager_create_negative_without_parameters(self): - result = 'Exception' - manager = services.ActiveDirectoryManager(api) - try: - result = manager.create() - except TypeError: - pass - assert result is 'Exception' - - def test_ad_manager_delete(self): - manager = services.ActiveDirectoryManager(api) - result = manager.delete('datacenter1', 'session1', 'test') - assert result is None - - def test_ad_manager_delete_with_named_parameters(self): - manager = services.ActiveDirectoryManager(api) - result = manager.delete(environment_id='datacenter1', - session_id='session1', - service_id='test') - assert result is None - - def test_ad_manager_delete_negative_with_two_parameters(self): - result = 'Exception' - manager = services.ActiveDirectoryManager(api) - try: - result = manager.delete('datacenter1', 'session1') - except TypeError: - pass - assert result == 'Exception' - - def test_ad_manager_delete_negative_with_one_parameter(self): - result = 'Exception' - manager = services.ActiveDirectoryManager(api) - try: - result = manager.delete('datacenter1') - except TypeError: - pass - assert result == 'Exception' - - def test_ad_manager_delete_negative_without_parameters(self): - result = 'Exception' - manager = services.ActiveDirectoryManager(api) - try: - result = manager.delete() - except TypeError: - pass - assert result == 'Exception' - - def test_iis_manager_list_with_one_parameter(self): - manager = services.WebServerManager(api) - result = manager.list('datacenter1') - assert result == [] - - def test_iis_manager_list_with_named_parameter(self): - manager = services.WebServerManager(api) - result = manager.list(environment_id='datacenter1') - assert result == [] - - def test_iis_manager_list_with_all_parameters(self): - manager = services.WebServerManager(api) - result = manager.list('test', '1') - assert result == [] - - def test_iis_manager_list_with_named_parameters(self): - manager = services.WebServerManager(api) - result = manager.list(environment_id='test', - session_id='1') - assert result == [] - - def test_iis_manager_list_negative_without_parameters(self): - result = 'Exception' - manager = services.WebServerManager(api) - try: - result = manager.list() - except TypeError: - pass - assert result == 'Exception' - - def test_iis_manager_create(self): - manager = services.WebServerManager(api) - result = manager.create('datacenter1', 'session1', 'test') - assert result.headers == {'X-Configuration-Session': 'session1'} - assert result.body == 'test' - - def test_iis_manager_create_with_named_parameters(self): - manager = services.WebServerManager(api) - result = manager.create(environment_id='datacenter', - session_id='session', - web_server='test2') - assert result.headers == {'X-Configuration-Session': 'session'} - assert result.body == 'test2' - - def test_iis_manager_create_negative_with_two_parameters(self): - result = 'Exception' - manager = services.WebServerManager(api) - try: - result = manager.create('datacenter1', 'session1') - except TypeError: - pass - assert result == 'Exception' - - def test_iis_manager_create_negative_with_one_parameter(self): - result = 'Exception' - manager = services.WebServerManager(api) - try: - result = manager.create('datacenter1') - except TypeError: - pass - assert result == 'Exception' - - def test_iis_manager_create_negative_without_parameters(self): - result = 'Exception' - manager = services.WebServerManager(api) - try: - result = manager.create() - except TypeError: - pass - assert result == 'Exception' - - def test_iis_manager_delete(self): - manager = services.WebServerManager(api) - result = manager.delete('datacenter1', 'session1', 'test') - assert result is None - - def test_iis_manager_delete_with_named_parameters(self): - manager = services.WebServerManager(api) - result = manager.delete(environment_id='datacenter', - session_id='session', - service_id='test') - assert result is None - - def test_iis_manager_delete_negative_with_two_parameters(self): - result = 'Exception' - manager = services.WebServerManager(api) - try: - result = manager.delete('datacenter1', 'session1') - except TypeError: - pass - assert result == 'Exception' - - def test_iis_manager_delete_negative_with_one_parameter(self): - result = 'Exception' - manager = services.WebServerManager(api) - try: - result = manager.delete('datacenter1') - except TypeError: - pass - assert result == 'Exception' - - def test_iis_manager_delete_negative_without_parameters(self): - result = 'Exception' - manager = services.WebServerManager(api) - try: - result = manager.delete() - except TypeError: - pass - assert result == 'Exception' - - def test_service_ad(self): - service_ad = services.ActiveDirectory(api, api) - assert service_ad.data() is not None - - def test_service_iis(self): - service_iis = services.ActiveDirectory(api, api) - assert service_iis.data() is not None - - def test_session_manager_list(self): - manager = sessions.SessionManager(api) - result = manager.list('datacenter1') - assert result == [] - - def test_session_manager_list_with_named_parameters(self): - manager = sessions.SessionManager(api) - result = manager.list(environment_id='datacenter1') - assert result == [] - - def test_session_manager_list_negative_without_parameters(self): - result = 'Exception' - manager = sessions.SessionManager(api) - try: - result = manager.list() - except TypeError: - pass - assert result == 'Exception' - - def test_session_manager_delete(self): - manager = sessions.SessionManager(api) - result = manager.delete('datacenter1', 'session1') - assert result is None - - def test_session_manager_delete_with_named_parameters(self): - manager = sessions.SessionManager(api) - result = manager.delete(environment_id='datacenter1', - session_id='session1') - assert result is None - - def test_session_manager_delete_negative_with_one_parameter(self): - result = 'Exception' - manager = sessions.SessionManager(api) - try: - result = manager.delete('datacenter1') - except TypeError: - pass - assert result == 'Exception' - - def test_session_manager_delete_negative_without_parameters(self): - result = 'Exception' - manager = sessions.SessionManager(api) - try: - result = manager.delete() - except TypeError: - pass - assert result == 'Exception' - - def test_session_manager_get(self): - manager = sessions.SessionManager(api) - result = manager.get('datacenter1', 'session1') - # WTF? - assert result.manager is not None - - def test_session_manager_configure(self): - manager = sessions.SessionManager(api) - result = manager.configure('datacenter1') - assert result is not None - - def test_session_manager_configure_with_named_parameter(self): - manager = sessions.SessionManager(api) - result = manager.configure(environment_id='datacenter1') - assert result is not None - - def test_session_manager_configure_negative_without_parameters(self): - result = 'Exception' - manager = sessions.SessionManager(api) - try: - result = manager.configure() - except TypeError: - pass - assert result == 'Exception' - - def test_session_manager_deploy(self): - manager = sessions.SessionManager(api) - result = manager.deploy('datacenter1', '1') - assert result is None - - def test_session_manager_deploy_with_named_parameters(self): - manager = sessions.SessionManager(api) - result = manager.deploy(environment_id='datacenter1', - session_id='1') - assert result is None - - def test_session_manager_deploy_negative_with_one_parameter(self): - result = 'Exception' - manager = sessions.SessionManager(api) - try: - result = manager.deploy('datacenter1') - except TypeError: - pass - assert result == 'Exception' - - def test_session_manager_deploy_negative_without_parameters(self): - result = 'Exception' - manager = sessions.SessionManager(api) - try: - result = manager.deploy() - except TypeError: - pass - assert result == 'Exception' - - def test_session_manager_reports(self): - manager = sessions.SessionManager(api) - result = manager.reports('datacenter1', '1') - assert result == [] - - def test_session_manager_reports_with_named_parameters(self): - manager = sessions.SessionManager(api) - result = manager.reports(environment_id='datacenter1', - session_id='1') - assert result == [] - - def test_session_manager_reports_negative_with_one_parameter(self): - result = 'Exception' - manager = sessions.SessionManager(api) - try: - result = manager.reports('datacenter1') - except TypeError: - pass - assert result == 'Exception' - - def test_session_manager_reports_negative_without_parameters(self): - result = 'Exception' - manager = sessions.SessionManager(api) - try: - result = manager.reports() - except TypeError: - pass - assert result == 'Exception' diff --git a/python-glazierclient/tools/install_venv.py b/python-glazierclient/tools/install_venv.py deleted file mode 100644 index 91903d6c..00000000 --- a/python-glazierclient/tools/install_venv.py +++ /dev/null @@ -1,75 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Copyright 2010 OpenStack LLC. -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Installation script for python-glazierclient's development virtualenv -""" - -import os -import subprocess -import sys - -import install_venv_common as install_venv - - -def print_help(): - help = """ - Glazier development environment setup is complete. - - Glazier development uses virtualenv to track and manage Python dependencies - while in development and testing. - - To activate the Glazier virtualenv for the extent of your current shell session - you can run: - - $ source .venv/bin/activate - - Or, if you prefer, you can run commands in the virtualenv on a case by case - basis by running: - - $ tools/with_venv.sh <your command> - - Also, make test will automatically use the virtualenv. - """ - print help - - -def main(argv): - root = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) - venv = os.path.join(root, '.venv') - pip_requires = os.path.join(root, 'tools', 'pip-requires') - test_requires = os.path.join(root, 'tools', 'test-requires') - py_version = "python%s.%s" % (sys.version_info[0], sys.version_info[1]) - project = 'python-glazierclient' - install = install_venv.InstallVenv(root, venv, pip_requires, test_requires, - py_version, project) - options = install.parse_args(argv) - install.check_python_version() - install.check_dependencies() - install.create_virtualenv(no_site_packages=options.no_site_packages) - install.install_dependencies() - install.run_command([os.path.join(venv, 'bin/python'), - 'setup.py', 'develop']) - install.post_process() - print_help() - -if __name__ == '__main__': - main(sys.argv) diff --git a/python-glazierclient/tools/install_venv_common.py b/python-glazierclient/tools/install_venv_common.py deleted file mode 100644 index fd9076f0..00000000 --- a/python-glazierclient/tools/install_venv_common.py +++ /dev/null @@ -1,219 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2013 OpenStack, LLC -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides methods needed by installation script for OpenStack development -virtual environments. - -Synced in from openstack-common -""" - -import argparse -import os -import subprocess -import sys - - -class InstallVenv(object): - - def __init__(self, root, venv, pip_requires, test_requires, py_version, - project): - self.root = root - self.venv = venv - self.pip_requires = pip_requires - self.test_requires = test_requires - self.py_version = py_version - self.project = project - - def die(self, message, *args): - print >> sys.stderr, message % args - sys.exit(1) - - def check_python_version(self): - if sys.version_info < (2, 6): - self.die("Need Python Version >= 2.6") - - def run_command_with_code(self, cmd, redirect_output=True, - check_exit_code=True): - """Runs a command in an out-of-process shell. - - Returns the output of that command. Working directory is self.root. - """ - if redirect_output: - stdout = subprocess.PIPE - else: - stdout = None - - proc = subprocess.Popen(cmd, cwd=self.root, stdout=stdout) - output = proc.communicate()[0] - if check_exit_code and proc.returncode != 0: - self.die('Command "%s" failed.\n%s', ' '.join(cmd), output) - return (output, proc.returncode) - - def run_command(self, cmd, redirect_output=True, check_exit_code=True): - return self.run_command_with_code(cmd, redirect_output, - check_exit_code)[0] - - def get_distro(self): - if (os.path.exists('/etc/fedora-release') or - os.path.exists('/etc/redhat-release')): - return Fedora(self.root, self.venv, self.pip_requires, - self.test_requires, self.py_version, self.project) - else: - return Distro(self.root, self.venv, self.pip_requires, - self.test_requires, self.py_version, self.project) - - def check_dependencies(self): - self.get_distro().install_virtualenv() - - def create_virtualenv(self, no_site_packages=True): - """Creates the virtual environment and installs PIP. - - Creates the virtual environment and installs PIP only into the - virtual environment. - """ - if not os.path.isdir(self.venv): - print 'Creating venv...', - if no_site_packages: - self.run_command(['virtualenv', '-q', '--no-site-packages', - self.venv]) - else: - self.run_command(['virtualenv', '-q', self.venv]) - print 'done.' - print 'Installing pip in venv...', - if not self.run_command(['tools/with_venv.sh', 'easy_install', - 'pip>1.0']).strip(): - self.die("Failed to install pip.") - print 'done.' - else: - print "venv already exists..." - pass - - def pip_install(self, *args): - self.run_command(['tools/with_venv.sh', - 'pip', 'install', '--upgrade'] + list(args), - redirect_output=False) - - def install_dependencies(self): - print 'Installing dependencies with pip (this can take a while)...' - - # First things first, make sure our venv has the latest pip and - # distribute. - # NOTE: we keep pip at version 1.1 since the most recent version causes - # the .venv creation to fail. See: - # https://bugs.launchpad.net/nova/+bug/1047120 - self.pip_install('pip==1.1') - self.pip_install('distribute') - - # Install greenlet by hand - just listing it in the requires file does - # not - # get it installed in the right order - self.pip_install('greenlet') - - self.pip_install('-r', self.pip_requires) - self.pip_install('-r', self.test_requires) - - def post_process(self): - self.get_distro().post_process() - - def parse_args(self, argv): - """Parses command-line arguments.""" - parser = argparse.ArgumentParser() - parser.add_argument('-n', '--no-site-packages', - action='store_true', - help="Do not inherit packages from global Python " - "install") - return parser.parse_args(argv[1:]) - - -class Distro(InstallVenv): - - def check_cmd(self, cmd): - return bool(self.run_command(['which', cmd], - check_exit_code=False).strip()) - - def install_virtualenv(self): - if self.check_cmd('virtualenv'): - return - - if self.check_cmd('easy_install'): - print 'Installing virtualenv via easy_install...', - if self.run_command(['easy_install', 'virtualenv']): - print 'Succeeded' - return - else: - print 'Failed' - - self.die('ERROR: virtualenv not found.\n\n%s development' - ' requires virtualenv, please install it using your' - ' favorite package management tool' % self.project) - - def post_process(self): - """Any distribution-specific post-processing gets done here. - - In particular, this is useful for applying patches to code inside - the venv. - """ - pass - - -class Fedora(Distro): - """This covers all Fedora-based distributions. - - Includes: Fedora, RHEL, CentOS, Scientific Linux - """ - - def check_pkg(self, pkg): - return self.run_command_with_code(['rpm', '-q', pkg], - check_exit_code=False)[1] == 0 - - def yum_install(self, pkg, **kwargs): - print "Attempting to install '%s' via yum" % pkg - self.run_command(['sudo', 'yum', 'install', '-y', pkg], **kwargs) - - def apply_patch(self, originalfile, patchfile): - self.run_command(['patch', originalfile, patchfile]) - - def install_virtualenv(self): - if self.check_cmd('virtualenv'): - return - - if not self.check_pkg('python-virtualenv'): - self.yum_install('python-virtualenv', check_exit_code=False) - - super(Fedora, self).install_virtualenv() - - def post_process(self): - """Workaround for a bug in eventlet. - - This currently affects RHEL6.1, but the fix can safely be - applied to all RHEL and Fedora distributions. - - This can be removed when the fix is applied upstream. - - Nova: https://bugs.launchpad.net/nova/+bug/884915 - Upstream: https://bitbucket.org/which_linden/eventlet/issue/89 - """ - - # Install "patch" program if it's not there - if not self.check_pkg('patch'): - self.yum_install('patch') - - # Apply the eventlet patch - self.apply_patch(os.path.join(self.venv, 'lib', self.py_version, - 'site-packages', - 'eventlet/green/subprocess.py'), - 'contrib/redhat-eventlet.patch') diff --git a/python-glazierclient/tools/pip-requires b/python-glazierclient/tools/pip-requires deleted file mode 100644 index 632d17be..00000000 --- a/python-glazierclient/tools/pip-requires +++ /dev/null @@ -1,5 +0,0 @@ -argparse -prettytable>=0.6,<0.7 -python-keystoneclient>=0.1.2 -httplib2 -iso8601>=0.1.4 diff --git a/python-glazierclient/tools/test-requires b/python-glazierclient/tools/test-requires deleted file mode 100644 index 98870ef5..00000000 --- a/python-glazierclient/tools/test-requires +++ /dev/null @@ -1,15 +0,0 @@ -distribute>=0.6.24 - -mock -anyjson -mox -nose -nose-exclude -nosexcover -openstack.nose_plugin -nosehtmloutput -pep8==1.3.3 -setuptools-git>=0.4 -sphinx>=1.1.2 -unittest2 -httpretty diff --git a/python-glazierclient/tools/with_venv.sh b/python-glazierclient/tools/with_venv.sh deleted file mode 100755 index c8d2940f..00000000 --- a/python-glazierclient/tools/with_venv.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -TOOLS=`dirname $0` -VENV=$TOOLS/../.venv -source $VENV/bin/activate && $@ diff --git a/python-glazierclient/tox.ini b/python-glazierclient/tox.ini deleted file mode 100644 index 244d2b6a..00000000 --- a/python-glazierclient/tox.ini +++ /dev/null @@ -1,46 +0,0 @@ -[tox] -envlist = py27,pep8 - -[testenv] -setenv = VIRTUAL_ENV={envdir} - NOSE_WITH_OPENSTACK=1 - NOSE_OPENSTACK_COLOR=1 - NOSE_OPENSTACK_RED=0.05 - NOSE_OPENSTACK_YELLOW=0.025 - NOSE_OPENSTACK_SHOW_ELAPSED=1 -deps = -r{toxinidir}/tools/pip-requires - -r{toxinidir}/tools/test-requires -commands = nosetests - -[testenv:pep8] -deps = pep8==1.3.3 -commands = pep8 --repeat --show-source glazierclient setup.py - -[testenv:venv] -commands = {posargs} - -[testenv:cover] -commands = nosetests --cover-erase --cover-package=glazierclient --with-xcoverage - -[tox:jenkins] -downloadcache = ~/cache/pip - -[testenv:jenkins26] -basepython = python2.6 -setenv = NOSE_WITH_XUNIT=1 -deps = file://{toxinidir}/.cache.bundle - -[testenv:jenkins27] -basepython = python2.7 -setenv = NOSE_WITH_XUNIT=1 -deps = file://{toxinidir}/.cache.bundle - -[testenv:jenkinscover] -deps = file://{toxinidir}/.cache.bundle -setenv = NOSE_WITH_XUNIT=1 -commands = nosetests --cover-erase --cover-package=glazierclient --with-xcoverage - -[testenv:jenkinsvenv] -deps = file://{toxinidir}/.cache.bundle -setenv = NOSE_WITH_XUNIT=1 -commands = {posargs} diff --git a/tests/REST_service/test.py b/tests/REST_service/test.py deleted file mode 100644 index 0957378c..00000000 --- a/tests/REST_service/test.py +++ /dev/null @@ -1,172 +0,0 @@ -# -*- coding: utf-8 -*- - - -import unittest2 -import requests -import json -import logging -import thread -import time - -logging.basicConfig() -LOG = logging.getLogger(' REST service tests') - -class TestSuite(unittest2.TestCase): - - def setUp(self): - self.max_count = 200 - self.url = 'http://localhost:8082/environments' - self.headers = {'X-Auth-Token': '3685674500ff83eb62b5c5d453e0cacd'} - self.lock_list = [] - self.responses = [] - self.state = 'stop' - - def tearDown(self): - self.headers = {} - - def run_in_parrallel(self, func, parameter): - lock = thread.allocate_lock() - lock.acquire() - self.lock_list.append(lock) - thread.start_new_thread(func, (parameter, lock)) - - def wait_threads(self): - self.state = 'run' - while(any([l.locked() for l in self.lock_list])): - pass - - LOG.critical(self.lock_list) - - def create_environment(self, name, lock): - while (self.state == 'stop'): - pass - - body = '{"name": "%s"}' % name - response = requests.request('POST', - self.url, - headers=self.headers, - data=body) - - self.responses.append(response) - - return lock.release() - - - def delete_environment(self, id, lock): - while (self.state == 'stop'): - pass - - id = '/' + id - - response = requests.request('DELETE', self.url+id, headers=self.headers) - - self.responses.append(response) - - return lock.release() - - def test_01_delete_environments(self): - - response = requests.request('GET', self.url, headers=self.headers) - - result = json.loads(response._content) - environments = result['environments'] - - for env in environments: - self.run_in_parrallel(self.delete_environment, env['id']) - - self.wait_threads() - - for response in self.responses: - assert response.status_code is 200 - - def test_02_list_environments(self): - - response = requests.request('GET', self.url, headers=self.headers) - - result = json.loads(response._content) - environments = result['environments'] - - assert len(environments) is 0 - - def test_03_create_environment(self): - - self.headers.update({'Content-Type': 'application/json'}) - body = '{"name": "test"}' - - response = requests.request('POST', self.url, headers=self.headers, - data=body) - - environment = json.loads(response._content) - - assert environment['name'] == 'test' - - def test_04_delete_environment(self): - - id = None - - response = requests.request('GET', self.url, headers=self.headers) - - result = json.loads(response._content) - environments = result['environments'] - - for env in environments: - if env['name'] == 'test': - id = '/' + env['id'] - - assert id is not None - - response = requests.request('DELETE', self.url+id, headers=self.headers) - - assert response.status_code is 200 - - def test_05_create_environments(self): - - self.headers.update({'Content-Type': 'application/json'}) - - for i in range(self.max_count): - name = "environment%s" % i - self.run_in_parrallel(self.create_environment, name) - - self.wait_threads() - - for response in self.responses: - assert response.status_code is 200 - - def test_06_list_environments(self): - - response = requests.request('GET', self.url, headers=self.headers) - - result = json.loads(response._content) - environments = result['environments'] - - assert len(environments) == self.max_count - - - def test_07_list_environments(self): - - response = requests.request('GET', self.url, headers=self.headers) - - result = json.loads(response._content) - environments = result['environments'] - - assert len(environments) > 0 - - def test_08_list_environments(self): - - response = requests.request('GET', self.url, headers=self.headers) - - result = json.loads(response._content) - environments = result['environments'] - - for env in environments: - assert env.get('id', None) is not None - assert env.get('name', None) is not None - assert env.get('status', None) is not None - assert env.get('updated', None) is not None - assert env.get('created', None) is not None - assert env.get('tenant_id', None) is not None - - - -if __name__ == '__main__': - unittest2.main() \ No newline at end of file diff --git a/tests/deploy.sh b/tests/deploy.sh deleted file mode 100755 index cad10a20..00000000 --- a/tests/deploy.sh +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/expect -d -# The following directories should be created for this script: -# /opt/stack/devstack -# /opt/stack/keero -# the ssh key should be in directory /opt/stack/.ssh/ -# the iso file with windows should be in directory /opt/stack/ - -set timeout 1200 - -send_user "\n\nStart to login to the test bed...\n\n" - -spawn /usr/bin/ssh [lindex $argv 0]@[lindex $argv 1] -expect "password" -send -- "EVYiMCVZX9\n" -expect "*#*" - -send -- "su - stack\n" -expect "*$*" - -send -- "sudo killall python\n" -expect "*$*" -send -- "cd ~/devstack\n" -expect "*$*" -send -- "./unstack.sh\n" -expect "*$*" -send -- "./stack.sh\n" -expect "*/usr/bin/service: 123: exec: status: not found*" -send -- "y\n" -expect "*stack.sh completed*" - -send -- "sudo rabbitmq-plugins enable rabbitmq_management\n" -expect "*$*" -send -- "sudo service rabbitmq-server restart\n" -expect "*$*" -send -- "sudo rabbitmqctl add_user keero keero\n" -expect "*$*" -send -- "sudo rabbitmqctl set_user_tags keero administrator\n" -expect "*$*" - - -send -- "source openrc admin admin\n" -expect "*$*" - -send -- "cd ~\n" -expect "*$*" - -send -- "nova keypair-add keero-linux-keys > heat_key.priv\n" -expect "*$*" - -send -- "glance image-create --name 'ws-2012-full' --is-public true --container-format ovf --disk-format qcow2 < ws-2012-full.qcow2\n" -expect "*$*" - -send -- "cd ~/keero\n" -expect "*$*" -send -- "git pull\n" -expect "/.ssh/id_rsa" -send -- "swordfish\n" -expect "*$*" -send -- "cp -Rf ~/keero/dashboard/windc /opt/stack/horizon/openstack_dashboard/dashboards/project\n" -expect "*$*" -send -- "cp -f ~/keero/dashboard/api/windc.py /opt/stack/horizon/openstack_dashboard/api/\n" -expect "*$*" -send -- "cd ~/keero/python-portasclient\n" -expect "*$*" -send -- "sudo python setup.py install\n" -expect "*$*" -send -- "cd ~/keero/portas\n" -expect "*$*" -send -- "./tools/with_venv.sh ./bin/portas-api --config-file=./etc/portas-api.conf & > ~/APIservice.log\n" -sleep 10 -send -- "\n" -expect "*$*" -send -- "cd ~/keero/conductor\n" -expect "*$*" -send -- "./tools/with_venv.sh ./bin/app.py & > ~/conductor.log\n" -sleep 10 -send -- "\n" -expect "*$*" -send -- "logout\n" -expect "*#*" - diff --git a/tests/selenium/conf.ini b/tests/selenium/conf.ini deleted file mode 100644 index 12af6f58..00000000 --- a/tests/selenium/conf.ini +++ /dev/null @@ -1,4 +0,0 @@ -[server] -address=http://172.18.124.101:8080 -user=admin -password=swordfish \ No newline at end of file diff --git a/tests/selenium/environments_page.py b/tests/selenium/environments_page.py deleted file mode 100644 index 0475463a..00000000 --- a/tests/selenium/environments_page.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import re -from services_page import ServicesPage -import page - - -class EnvironmentsPage(page.Page): - name = 'Environments' - - def create_environment(self, name): - self.Refresh() - self.Button('Create Environment').Click() - self.EditBox('id_name').Set(name) - self.Button('Create').Click() - - def delete_environment(self, name): - self.Refresh() - - link = self.Link(name).Address() - environment_id = re.search('tabula/(\S+)', link).group(0)[7:-1] - - self.Button('More', environment_id).Click() - self.Button('Delete', environment_id).Click() - # confirm: - self.Button('Delete Environment').Click() - - def select_environment(self, name): - self.Link(name).Click() - page = ServicesPage(self.driver) - return page - - def deploy_environment(self, name): - self.Refresh() - - link = self.Link(name).Address() - environment_id = re.search('tabula/(\S+)', link).group(0)[7:-1] - - self.Button('More', environment_id).Click() - self.Button('Deploy', environment_id).Click() - - def get_environment_status(self, name): - self.Refresh() - - link = self.Link(name).Address() - environment_id = re.search('tabula/(\S+)', link).group(0)[7:-1] - - return self.TableCell('Status', environment_id).Text() diff --git a/tests/selenium/login_page.py b/tests/selenium/login_page.py deleted file mode 100644 index 9d5b2b17..00000000 --- a/tests/selenium/login_page.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import ConfigParser -import page - - -class LoginPage(page.Page): - - def login(self): - config = ConfigParser.RawConfigParser() - config.read('conf.ini') - url = config.get('server', 'address') - user = config.get('server', 'user') - password = config.get('server', 'password') - - self.Open(url) - - self.EditBox('username').Set(user) - self.EditBox('password').Set(password) - xpath = "//button[@type='submit']" - self.Button(xpath).Click() - - return self diff --git a/tests/selenium/objects.xml b/tests/selenium/objects.xml deleted file mode 100644 index 8af03755..00000000 --- a/tests/selenium/objects.xml +++ /dev/null @@ -1,73 +0,0 @@ -<objects> - <object> - <type>Button</type> - <name>Create</name> - <parameter>//input[@value='Create']</parameter> - </object> - <object> - <type>Button</type> - <pagename>Services</pagename> - <name>More</name> - <parameter>.//*[@id='services__row__%s']/td[5]/div/a[2]</parameter> - </object> - <object> - <type>Button</type> - <pagename>Services</pagename> - <name>Delete</name> - <parameter>services__row_%s__action_delete</parameter> - </object> - <object> - <type>Button</type> - <pagename>Services</pagename> - <name>CreateService</name> - <parameter>services__action_CreateService</parameter> - </object> - <object> - <type>Button</type> - <pagename>DataCenters</pagename> - <name>More</name> - <parameter>.//*[@id='windc__row__%s']/td[4]/div/a[2]</parameter> - </object> - <object> - <type>Button</type> - <pagename>DataCenters</pagename> - <name>Delete</name> - <parameter>windc__row_%s__action_delete</parameter> - </object> - <object> - <type>Button</type> - <pagename>DataCenters</pagename> - <name>Deploy</name> - <parameter>windc__row_%s__action_deploy</parameter> - </object> - <object> - <type>TableCell</type> - <pagename>DataCenters</pagename> - <name>Status</name> - <parameter>.//*[@id='windc__row__%s']/td[3]</parameter> - </object> - <object> - <type>TableCell</type> - <pagename>ServicesDetails</pagename> - <name>Name</name> - <parameter>.//*[@id='services_details___service']/div/dl/dd[1]</parameter> - </object> - <object> - <type>TableCell</type> - <pagename>ServicesDetails</pagename> - <name>Domain</name> - <parameter>.//*[@id='services_details___service']/div/dl/dd[3]</parameter> - </object> - <object> - <type>Link</type> - <pagename>ServicesDetails</pagename> - <name>Service</name> - <parameter>.//*[@id='services_details']/li[1]/a</parameter> - </object> - <object> - <type>TableCell</type> - <pagename>Services</pagename> - <name>Status</name> - <parameter>.//*[@id='services__row__%s']/td[4]</parameter> - </object> -</objects> \ No newline at end of file diff --git a/tests/selenium/page.py b/tests/selenium/page.py deleted file mode 100644 index f4050633..00000000 --- a/tests/selenium/page.py +++ /dev/null @@ -1,276 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import logging -from selenium.webdriver.support.ui import Select -import xml.etree.ElementTree as ET - - -logging.basicConfig() -LOG = logging.getLogger(' Page object: ') -""" - Disable selenium logging: -""" -logger = logging.getLogger('selenium.webdriver.remote.remote_connection') -logger.setLevel('ERROR') - - -class ObjectsLibrary: - file = None - objects = [] - - def __init__(self, file_name='objects.xml'): - """ - Initialization of the Objects Library. - Read objects descriptions from XML file. - """ - self.file = file_name - tree = ET.parse(self.file) - objects = tree.getroot() - self.objects = [] - for element in objects: - object = {} - for parameter in element: - object.update({parameter.tag: parameter.text}) - self.objects.append(object) - - def get_object(self, name, pagename): - """ - Search objects in Objects Library. - """ - for object in self.objects: - obj_pagename = object.get('pagename', None) - if object['name'] == name and (obj_pagename == pagename - or obj_pagename is None): - return object['parameter'] - return None - - -class TableCellClass: - table = None - - def __init__(self, obj): - if not obj: - LOG.error('TableCell does not found') - self.table = obj - - def Text(self): - if self.table: - LOG.critical(self.table.text) - return self.table.text - else: - return '' - - -class ButtonClass: - button = None - - def __init__(self, obj): - if not obj: - LOG.error('Button does not found') - self.button = obj - - def Click(self): - if self.button: - self.button.click() - - def isPresented(self): - if self.button: - return True - return False - - -class LinkClass: - link = None - - def __init__(self, obj): - if not obj: - LOG.error('Link does not found') - self.link = obj - - def Click(self): - if self.link: - self.link.click() - - def isPresented(self): - if self.link: - return True - return False - - def Address(self): - if self.link: - return self.link.get_attribute('href') - else: - return '' - - -class EditBoxClass: - - def __init__(self, obj): - if not obj: - LOG.error('EditBox does not found') - self.edit = obj - - def isPresented(self): - if self.edit: - return True - return False - - def Set(self, value): - if self.edit: - try: - self.edit.clear() - self.edit.send_keys(value) - except: - LOG.error('Can not set value for text box.') - - def Text(self): - if self.edit: - return self.edit.get_text() - else: - return '' - - -class DropDownListClass: - select = None - - def __init__(self, obj): - if not obj: - LOG.error('DropDownList does not found') - self.select = obj - - def isPresented(self): - if self.select is not None: - return True - return False - - def Set(self, value): - if self.select: - try: - Select(self.select).select_by_visible_text(value) - except: - LOG.error('Can not select element %s from drop down list.' - .format(value)) - - def Text(self): - if self.select: - return self.select.get_text() - else: - return '' - - -error_msg = """ - Object with parameter: %s - does not found on page. - """ - - -class Page: - - driver = None - timeout = 10 - lib = None - name = None - - def __init__(self, driver): - driver.set_page_load_timeout(self.timeout) - driver.implicitly_wait(0.01) - self.driver = driver - - def _find_element(self, name, parameter=None): - """ - This method allows to find element, - based on descriptions in Object Library, - xpath, id, name or pertial link text. - If parameter != None will be used name % parameter - """ - lib = ObjectsLibrary() - if lib.get_object(name, self.name): - name = lib.get_object(name, self.name) - - if parameter: - name = name % parameter - - obj = None - k = 0 - - while (obj is None and k < self.timeout): - k += 1 - - try: - obj = self.driver.find_element_by_name(name) - return obj - except: - pass - try: - obj = self.driver.find_element_by_id(name) - return obj - except: - pass - try: - obj = self.driver.find_element_by_xpath(name) - return obj - except: - pass - try: - obj = self.driver.find_element_by_partial_link_text(name) - return obj - except: - pass - - LOG.error(error_msg % name) - return None - - def Open(self, url): - self.driver.get(url) - - def Refresh(self): - self.driver.refresh() - - def TableCell(self, name, parameter=None): - obj = self._find_element(name, parameter) - table = TableCellClass(obj) - return table - - def Button(self, name, parameter=None): - obj = self._find_element(name, parameter) - button = ButtonClass(obj) - return button - - def Link(self, name, parameter=None): - obj = self._find_element(name, parameter) - link = LinkClass(obj) - return link - - def EditBox(self, name, parameter=None): - obj = self._find_element(name, parameter) - edit = EditBoxClass(obj) - return edit - - def DropDownList(self, name, parameter=None): - obj = self._find_element(name, parameter) - select = DropDownListClass(obj) - return select - - def Navigate(self, path): - """ - This method allows to navigate by - webUI menu button and links to - the specific page - """ - steps = path.split(':') - - for step in steps: - self.Button(step).Click() diff --git a/tests/selenium/services_details_page.py b/tests/selenium/services_details_page.py deleted file mode 100644 index eefafd4e..00000000 --- a/tests/selenium/services_details_page.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import page - - -class ServicesDetailsPage(page.Page): - - name = 'ServicesDetails' - - def get_service_name(self): - self.Refresh() - self.Link('Service').Click() - return self.TableCell('Name').Text() - - def get_service_domain(self): - self.Refresh() - self.Link('Service').Click() - return self.TableCell('Domain').Text() \ No newline at end of file diff --git a/tests/selenium/services_page.py b/tests/selenium/services_page.py deleted file mode 100644 index c511bfa0..00000000 --- a/tests/selenium/services_page.py +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import page -import re -from services_details_page import ServicesDetailsPage - - -class ServicesPage(page.Page): - - name = 'Services' - - def create_service(self, parameters): - service_type = parameters[0] - parameters = parameters[1] - self.Refresh() - - self.Button('CreateService').Click() - self.DropDownList('0-service').Set(service_type) - self.Button('wizard_goto_step').Click() - - for key in parameters: - try: - self.EditBox(key).Set(parameters[key]) - except: - pass - try: - self.DropDownList(key).Set(parameters[key]) - except: - pass - - self.Button('Create').Click() - - def delete_service(self, name): - self.Refresh() - - link = self.Link(name).Address() - - service_id = re.search('tabula/(\S+)', link).group(0)[7:-1] - - self.Button('More', service_id).Click() - self.Button('Delete', service_id).Click() - # confirm: - self.Button('Delete Service').Click() - - def select_service(self, name): - self.Link(name).Click() - page = ServicesDetailsPage(self.driver) - return page - - def get_service_status(self, name): - self.Refresh() - - link = self.Link(name).Address() - service_id = re.search('tabula/(\S+)', link).group(0)[7:-8] - - return self.TableCell('Status', service_id).Text() diff --git a/tests/selenium/test.py b/tests/selenium/test.py deleted file mode 100644 index 87acf6bf..00000000 --- a/tests/selenium/test.py +++ /dev/null @@ -1,182 +0,0 @@ -# Copyright (c) 2013 Mirantis Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import unittest2 -import logging -from login_page import LoginPage -from environments_page import EnvironmentsPage -from selenium import webdriver - - -logging.basicConfig() -LOG = logging.getLogger(' Tests: ') - - -def generate_ad(name="test", count=1): - """ - This function generates parameters for - Active Directory service - """ - ad_parameters = {'1-dc_name': name, - '1-dc_count': count, - '1-adm_password': "P@ssw0rd", - '1-recovery_password': "P@ssw0rd2"} - return ['Active Directory', ad_parameters] - -def generate_iis(name="test", domain="test"): - """ - This function generates parameters for - Internet Information Services service - """ - iis_parameters = {'1-iis_name': name, - '1-adm_password': "P@ssw0rd", - '1-iis_domain': domain} - return ['Internet Information Services', iis_parameters] - - -environment_for_deploy = 'environment_for_deploy' - - -class SanityTests(unittest2.TestCase): - - screenshots = 0 # Make screenshots for the end of each test - - @classmethod - def setUpClass(self): - """ - Open browser, navigate to the login page, - login and navigate to the Windows Data Centers page - """ - driver = webdriver.Firefox() - self.page = LoginPage(driver) - self.page.login() - - @classmethod - def tearDownClass(self): - """ - Close browser - """ - self.page.driver.close() - - def setUp(self): - """ - Navigate to the start page - """ - self.page.Navigate('Project:Environments') - self.page = EnvironmentsPage(driver) - - def tearDown(self): - """ - Make screenshot - """ - self.screenshots += 1 - self.page.driver.save_screenshot("screen_%s.png" % self.screenshots) - - def test_001_create_environment(self): - self.page.create_environment('dc1') - assert self.page.Link('dc1').isPresented() - - def test_002_delete_environment(self): - self.page.delete_environment('dc1') - assert not self.page.Link('dc1').isPresented() - - def test_003_configure_environment_before_deploy(self): - ad_name = "AD.net" - iis_name = "iis_server" - self.page.create_environment(environment_for_deploy) - self.page = self.page.select_environment(environment_for_deploy) - - self.page.create_service(generate_ad(ad_name, 2)) - assert self.page.Link(ad_name).isPresented() - - self.page.create_service(generate_iis(iis_name, ad_name)) - assert self.page.Link(iis_name).isPresented() - - def test_004_deploy_environment(self): - self.page.deploy_environment(environment_for_deploy) - status = self.page.get_environment_status(environment_for_deploy) - assert 'Deploy in progress' in status - - def test_005_create_environments(self): - for i in range(1, 10): - name = "environment" + str(i) - self.page.create_environment(name) - assert self.page.Link(name).isPresented() - - def test_006_delete_environments(self): - self.page.delete_environment('environment1') - self.page.delete_environment('environment9') - assert not self.page.Link('environment1').isPresented() - assert not self.page.Link('environment9').isPresented() - - for i in range(2, 9): - name = 'environment' + str(i) - assert self.page.Link(name).isPresented() - - def test_007_create_service_ad(self): - name = "dc001.local" - self.page.create_environment('test05') - self.page = self.page.select_environment('test05') - self.page.create_service(generate_ad(name, 1)) - assert self.page.Link(name).isPresented() - - def test_008_create_service_ad_two_instances(self): - name = "dc002.local" - self.page.create_environment('test06') - self.page = self.page.select_environment('test06') - self.page.create_service(generate_ad(name, 2)) - assert self.page.Link(name).isPresented() - - def test_009_create_service_ad_with_iis(self): - ad_name = "dc003.local" - self.page.create_environment('test07') - self.page = self.page.select_environment('test07') - self.page.create_service(generate_ad(ad_name, 3)) - assert self.page.Link(ad_name).isPresented() - - for i in range(5): - iis_name = 'iis_server' + str(i) - self.page.create_service(generate_iis(iis_name, ad_name)) - assert self.page.Link(iis_name).isPresented() - - def test_010_delete_environment_with_services(self): - name = "test07" - self.page.delete_environment(name) - assert not self.page.Link(name).isPresented() - - def test_011_service_deploy_in_progress_status(self): - ad_name = "AD.net" - iis_name = "iis_server" - self.page = self.page.select_environment(environment_for_deploy) - ad_status = self.page.get_service_status(ad_name) - iis_status = self.page.get_service_status(iis_name) - - assert 'Deploy in progress' in ad_status - assert 'Deploy in progress' in iis_status - - def test_012_show_service_details_for_deploy(self): - ad_name = "AD.net" - iis_name = "iis_server" - self.page = self.page.select_environment(environment_for_deploy) - self.page = self.page.select_service(iis_name) - name = self.page.get_service_name() - domain = self.page.get_service_domain() - - assert name == iis_name - assert name == ad_name - - -if __name__ == '__main__': - unittest2.main() diff --git a/tests/selenium/tools/test_requires b/tests/selenium/tools/test_requires deleted file mode 100644 index 3dc2329e..00000000 --- a/tests/selenium/tools/test_requires +++ /dev/null @@ -1,8 +0,0 @@ -xvfb -x11-xkb-utils -xfonts-100dpi -xfonts-75dpi -xfonts-scalable -xfonts-cyrillic -xserver-xorg-core -selenium \ No newline at end of file diff --git a/tests/selenium/tox.ini b/tests/selenium/tox.ini deleted file mode 100644 index 06904ba0..00000000 --- a/tests/selenium/tox.ini +++ /dev/null @@ -1,28 +0,0 @@ -[tox] -envlist = py27,pep8 - -[testenv] -setenv = VIRTUAL_ENV={envdir} - NOSE_WITH_OPENSTACK=1 - NOSE_OPENSTACK_COLOR=1 - NOSE_OPENSTACK_RED=0.05 - NOSE_OPENSTACK_YELLOW=0.025 - NOSE_OPENSTACK_SHOW_ELAPSED=1 -deps = -r{toxinidir}/tools/test-requires -commands = Xvfb -fp /usr/share/fonts/X11/misc/ :22 -screen 0 1024x768x16 2>&1 & export DISPLAY=:22 & nosetests - -[testenv:venv] -commands = {posargs} - -[tox:jenkins] -downloadcache = ~/cache/pip - -[testenv:jenkins27] -basepython = python2.7 -setenv = NOSE_WITH_XUNIT=1 -deps = file://{toxinidir}/.cache.bundle - -[testenv:jenkinsvenv] -deps = file://{toxinidir}/.cache.bundle -setenv = NOSE_WITH_XUNIT=1 -commands = {posargs}