Compare commits
18
Commits
cc40a109c8
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5401b7e96d | ||
|
|
0985d285b9 | ||
|
|
bf964bde34 | ||
|
|
e8df23c2e2 | ||
|
|
849a4c2796 | ||
|
|
f7421c1155 | ||
|
|
9e0fdd7b7b | ||
|
|
3bc7cea1d1 | ||
|
|
90aa268918 | ||
|
|
caaab5e0f7 | ||
|
|
3e89a13883 | ||
|
|
3e3fa0f7ca | ||
|
|
ab088906b8 | ||
|
|
a8bfd3de9e | ||
|
|
46169b449e | ||
|
|
55fa955326 | ||
|
|
2fdcd9598a | ||
|
|
bba1c0fe0c |
@@ -0,0 +1,11 @@
|
||||
<hr/>
|
||||
test
|
||||
<hr/>
|
||||
<cfflush/>
|
||||
<!--- <cftry>
|
||||
<cfdump var=#session#/>
|
||||
<cfcatch type="any"><cfdump var=#cfcatch#/></cfcatch>
|
||||
</cftry> --->
|
||||
|
||||
<cfmodule template="mod/crm_contract.cfm" wz="WZ01348"/>
|
||||
<cfdump var=#qComponent#/>
|
||||
+294
-116
@@ -8,6 +8,7 @@
|
||||
<!--- Set up the application. --->
|
||||
<cfset this.Name = "PAYG-REPORT" />
|
||||
<cfset this.applicationTimeout = createTimeSpan( 0, 3, 0, 0 ) />
|
||||
<cfset this.requestTimeout = createTimeSpan( 0, 0, 2, 0 )/>
|
||||
<cfset this.sessionmanagement="Yes"/>
|
||||
<cfset this.clientmanagement="No"/>
|
||||
<cfset this.sessiontimeout=CreateTimeSpan(0, 1, 0, 0)/>
|
||||
@@ -15,43 +16,59 @@
|
||||
<cfset this.mappings = structNew() />
|
||||
<cfset this.mappings["/mod"] = getDirectoryFromPath(getCurrentTemplatePath()) & "mod/" />
|
||||
<cfset this.customTagPaths = expandPath(getDirectoryFromPath(getCurrentTemplatePath()) & "mod")/>
|
||||
<!--- <cfset this.nullSupport = true/> --->
|
||||
|
||||
<!--- SSO --->
|
||||
<cfset this.client_id = "payg-report.deck.nubes.ru"/>
|
||||
<cfset this.auth_endpoint = "https://keycloak.nubes.ru/realms/cloud/protocol/openid-connect/auth" />
|
||||
<cfset this.logout_endpoint = "https://keycloak.nubes.ru/realms/cloud/protocol/openid-connect/logout" />
|
||||
<cfset this.access_token_endpoint = "https://keycloak.nubes.ru/realms/cloud/protocol/openid-connect/token" />
|
||||
<cfset this.idpCertUrl = "https://keycloak.nubes.ru/realms/cloud/protocol/openid-connect/certs" />
|
||||
<cfset this.client_secret = createObject("java", "java.lang.System").getEnv("IDP_CLIENT_SECRET")/>
|
||||
<!--- <cfset this.iam_url = "https://auth-api.ngcloud.ru/api/v1/auth/user"/> --->
|
||||
<cfset this.iamServiceUrl = "https://auth-api-dev.ngcloud.ru/api/v1/auth/user "/>
|
||||
<cfset this.redirect_uri = "https://#CGI.SERVER_NAME##CGI.SCRIPT_NAME#"/><!--- куда возвращаться от IDP --->
|
||||
<cfset this.crm_cache_host = "elma-cache.adl.nubes.ru"/><!--- *** почему-то приходится устанавливать серт sslCertificateInstall, иначе не коннектится --->
|
||||
<cfset request.crm_cache_base = "https://#this.crm_cache_host#/contract_ls.cfm"/>
|
||||
|
||||
<cfset this.datasource = "rpt"/>
|
||||
<cfset this.datasource = "rpt"/><!--- к буферной базе --->
|
||||
<cfset this.defaultdatasource = this.datasource/>
|
||||
<cfset request.DS = "#this.datasource#">
|
||||
<cfset request.language="">
|
||||
<!--- request scope is available in pseudoconstructor
|
||||
see also https://www.bennadel.com/blog/1437-coldfusion-scope-existence-during-various-request-types-and-events.htm --->
|
||||
<cfset request.DS = "#this.datasource#"/>
|
||||
<cfset request.language=""/>
|
||||
<cfset getDS(this.datasource)/>
|
||||
<!--- кажется, нужно инициализировать датасорцы в псевдоконструкторе - onRequest не получается --->
|
||||
<!--- *** проверить, что есть - если есть, не создавать --->
|
||||
|
||||
|
||||
<!--- это работает с административно заданным датасорцем, хотя, казалось бы, не должно
|
||||
(без окружения функция вернет пустую структуру). Видимо, административный датасорц обнаруживается раньше.
|
||||
Проверять на пустоту не хочется, чтобы не плодить в псевдоконструкторе переменные --->
|
||||
<!--- <cfdump var=#variables#/> --->
|
||||
|
||||
|
||||
<cffunction
|
||||
<cffunction
|
||||
name="OnApplicationStart"
|
||||
access="public"
|
||||
returntype="boolean"
|
||||
output="false"
|
||||
hint="Fires when the application is first created.">
|
||||
|
||||
<!--- *** Lucee specific function --->
|
||||
<cfset sslCertificateInstall(host="elma-cache.adl.nubes.ru", port=443)/><!--- ************************ duplicate address --->
|
||||
<!--- *** мы не проверяем срок жизни сертификата и его отзыв--->
|
||||
<!--- Obtain idp certificate OnApplicationStart --->
|
||||
<cfset application.idpCertificate = getIdpCertificate(this.idpCertUrl)/>
|
||||
<!--- <cfset this.iamServiceUrl = locateIamService()/> --->
|
||||
|
||||
<!--- <cfreturn super.onApplicationStart() /> --->
|
||||
<cfreturn true />
|
||||
</cffunction>
|
||||
|
||||
<cffunction name="onRequestStart" returnType="boolean">
|
||||
<cfargument name="targetPage" type="string" required="true" />
|
||||
|
||||
<cfif structKeyExists(url, "application_reset")>
|
||||
<cfset ApplicationStop() />
|
||||
<cflocation url="index.cfm" addtoken="false" />
|
||||
</cfif>
|
||||
<cfreturn true />
|
||||
</cffunction>
|
||||
|
||||
|
||||
<cffunction
|
||||
name="OnRequest"
|
||||
@@ -77,7 +94,8 @@
|
||||
|
||||
<!--- global settings --->
|
||||
<cfset request.RECORDS_PER_PAGE=500/>
|
||||
<cfset request.APP_VERSION="0.00.010"/>
|
||||
<cfset request.APP_VERSION="0.00.030"/>
|
||||
<cfheader name="X-Application-Version" value=#request.APP_VERSION#/>
|
||||
<cfset request.STAND=getStand()/>
|
||||
|
||||
<!--- application constants --->
|
||||
@@ -141,6 +159,7 @@
|
||||
<cfset request.APP_NAME=this.Name/>
|
||||
<cfset idpCertificateExists = structKeyExists(application,"idpCertificate")/>
|
||||
</cflock>
|
||||
|
||||
<cfif NOT idpCertificateExists>
|
||||
<!--- Obtain IDP Certificate (onRequest) --->
|
||||
<cfset var idpCertificate = getIdpCertificate(this.idpCertUrl) />
|
||||
@@ -151,42 +170,137 @@
|
||||
<!--- <cfoutput>onRequest:check for cert finished #(getTickCount()-request.startTickCount)#</cfoutput> --->
|
||||
|
||||
|
||||
<cfset this.redirect_uri = "https://#CGI.SERVER_NAME##CGI.SCRIPT_NAME#" />
|
||||
|
||||
<cfinclude template="inc/functions.cfm"/>
|
||||
|
||||
<cfif structKeyExists(url,"logout")>
|
||||
<cflock scope="session" type="exclusive" timeout="3">
|
||||
<cfset structDelete(session, "auth")/>
|
||||
</cflock>
|
||||
</cfif>
|
||||
|
||||
<cfcookie name="CFID" value="#session.CFID#"/>
|
||||
<cfcookie name="CFTOKEN" value="#session.CFTOKEN#"/>
|
||||
|
||||
<cfinclude template="inc/functions.cfm"/>
|
||||
|
||||
<!--- SSO --->
|
||||
<cflock scope="session" type="exclusive" timeout="3">
|
||||
<!---
|
||||
<cfdump var=#session#/>
|
||||
<cfoutput>#(getTickCount()-request.startTickCount)#</cfoutput>--->
|
||||
<!---
|
||||
Это первая проба, с сессией
|
||||
Когда протухнет сессия, мы можем пойти к IDP и повторно аутентифицироваться. Поскольку у нас сохраняются куки IDP, его сессия, возможно, будет жива. Если мы обновляли сессию IDP в другом приложении SSO, по всей видимости, она будет продолжаться. Если мы видим, что сессия IDP состарилась и хочет протухнуть, мы можем ее освежить и получить новый access token (который мы пока не используем - мы пользуемся ответом IDP) Наверное, правильно обходиться для этих целей вообще без сессии *** --->
|
||||
<!---
|
||||
проверить sso
|
||||
? сделать рефреш
|
||||
? сделать логаут
|
||||
? сделать отображение ошибки IDP
|
||||
+ сделать получение сертификата
|
||||
<!--- Если без сессии. Проверяем наличие токена в заголовке (и в куках?)
|
||||
Если его нет, идем к IDP за токеном. Получив токен, складываем его в куки
|
||||
Если токен есть, распаковываем его. Проверяем протухание. Если прошла установленная часть времени жизни, идем за рефрешем (внимание: это сработает только в браузере,
|
||||
если клиент не умеет редиректы - то токен должен быть достаточно свежий)
|
||||
(для начала делаем без рефреша, только проверяем протухание)
|
||||
А рефреш можно сделать на серверной стороне?
|
||||
Кладем данные из токена в реквест и наслаждаемся --->
|
||||
<!--- Вариант: если есть Authorization:bearer, идем с ним к IAM --->
|
||||
|
||||
--->
|
||||
<cfif structKeyExists(session, "auth")>
|
||||
<cfset request.auth = structCopy(session.auth)/>
|
||||
<!--- <cfset request.auth.wz = "WZ01553"/> --->
|
||||
<!--- тут нужно сделать проверку и рефреш токена --->
|
||||
<!--- сессия есть --->
|
||||
<cfelse>
|
||||
<!--- сессии нет --->
|
||||
<cfset session.auth_state=createGUID().toString()/>
|
||||
<cfscript>
|
||||
var requestData = GetHttpRequestData();
|
||||
var headers = requestData.headers;
|
||||
|
||||
<cfscript>
|
||||
jwt = new lib.jwt(this.client_secret);
|
||||
idp = new lib.oauth2(this.client_id, this.client_secret, this.auth_endpoint, this.access_token_endpoint, this.redirect_uri);
|
||||
//var authorizationHeader = server.system.environment?.AUTHORIZATION;
|
||||
|
||||
if (structKeyExists(headers,"Authorization")) {
|
||||
request.auth_header = headers.Authorization;
|
||||
} else {
|
||||
//request.auth_header = createObject("java", "java.lang.System").getEnv("AUTHORIZATION");
|
||||
request.auth_header = server.system.environment?.AUTHORIZATION; //так короче
|
||||
if (isNull(request.auth_header)){ /*for local debug we can inject long-living token into environment*/
|
||||
structDelete(request,"auth_header");
|
||||
} else {
|
||||
request.auth_header = "Bearer #request.auth_header#";
|
||||
}
|
||||
}
|
||||
|
||||
// if (structKeyExists(headers,"authorization")) { // аутентификация для клиента ЛК
|
||||
if (structKeyExists(request,"auth_header")) { // аутентификация для клиента ЛК
|
||||
var authorizationHeader = request.auth_header;
|
||||
if (authorizationHeader.startsWith("Bearer ")) {
|
||||
var bearerToken = Mid(authorizationHeader, 8);
|
||||
//writeDump(bearerToken);
|
||||
//var token=toString(binaryDecode(bearerToken, "base64"));
|
||||
//writeDump(token);
|
||||
//jwt = new lib.jwt(this.client_secret);
|
||||
//lock scope="application" type="readonly" timeout="1" {
|
||||
// var token_data = (jwt.decode(token, application.idpCertificate,"RS256"));
|
||||
//}
|
||||
var result="";
|
||||
//try {
|
||||
var iamService = new http(method = "GET", charset = "utf-8", url = #this.iamServiceUrl#, timeout="5");
|
||||
iamService.addParam(type = "HEADER", name = "Accept", value = "application/json");
|
||||
iamService.addParam(type = "HEADER", name = "Authorization", value = "#authorizationHeader#"); //passthrough
|
||||
//writedump(this.iamServiceUrl);abort;
|
||||
var resp = iamService.send();
|
||||
//if (resp.status_code NEQ 200) throw("IDP response not OK");
|
||||
//writedump(resp);abort;
|
||||
var prefix = resp.getPrefix();
|
||||
if (prefix.status_code NEQ 200) {
|
||||
//writedump(this.iamServiceUrl);
|
||||
//writedump(resp);
|
||||
var iamStatusCode = (isValid("integer", prefix.status_code)) ? val(prefix.status_code) : 500;
|
||||
throw(message="IAM error", detail="URL: #this.iamServiceUrl# Status Code: #prefix.status_code#");
|
||||
//abort;
|
||||
//throw("IDP response not OK");
|
||||
}
|
||||
result = prefix.filecontent;
|
||||
var idpUserData=deserializeJson(result);
|
||||
request.auth.wz=idpUserData.userInfo.ClientId;
|
||||
|
||||
//writeDump(idpUserData);
|
||||
|
||||
|
||||
request.auth.login = idpUserData.userInfo.login;
|
||||
//request.usrUid=idpUserData.userInfo.contactId;//userId; //GUID!
|
||||
//writedump(idpUserData);abort;
|
||||
//} catch (e) {
|
||||
/*if (fileExists("#GetDirectoryFromPath(GetCurrentTemplatePath())#/etc/local-debug")) { //true for local debug without IDP, etc/* does not go to repository
|
||||
var result='{"accounts":[{"login":"","type":"telegram"}],"avatar":["d2d2b7ac-50af-432b-b7c4-f7d6561e288a"],"company":"ООО «НУБЕС»","companyId":"8ec70ac0-546d-42a7-8cff-339c8fb51a23","contactId":"983967a3-58c2-4cdd-84a5-8b427ccfac82","email":"smishchuk@nubes.ru","externalUser":false,"fio":{"fullName":"Мищук Сергей ","name":"Сергей","secondName":"","surname":"Мищук"},"groupIds":["94bf5be7-52f4-5c13-87c3-513786934685","ab12b6b8-0265-4683-a5c2-5e1a74a55216","aff008c3-7443-50f6-86e1-ecff3cd3b04d","d6000da0-c9aa-55eb-9882-f118b432730b","d89a33dc-3177-5854-9580-f7f860a5ab7c","ddfe2555-9ef4-42cb-9a2b-7f24e61e7747","df12926f-ecb8-5479-857f-6d291464baad","fda5c295-230a-5025-9797-b8b4e99e08aa","2be9b4b6-94d1-59f9-a649-cab228d82169","64fe6f5c-a91b-5fea-a7ca-d9823701ebd4"],"integration":{"serviceId":""},"login":"smishchuk@nubes.ru","mobilePhone":[],"position":"","userId":"d72530e1-66a4-412f-a046-38153c4e5405"}';}
|
||||
*/
|
||||
//writedump(resp);
|
||||
//return representationOf( {"exception"=e} );
|
||||
//rethrow(e);
|
||||
//}
|
||||
}
|
||||
} else {
|
||||
//точно мы так не словим дедлок ВПР
|
||||
lock scope="session" type="readonly" timeout="3" {
|
||||
if (structKeyExists(session, "auth")) {
|
||||
request.auth = structCopy(session.auth);
|
||||
}
|
||||
}
|
||||
if (structKeyExists(request, "auth") AND Now() < request.auth.exp) {
|
||||
|
||||
if (dateDiff("s", request.auth.iat, Now()) > request.auth.refresh_expires_in/1.5 AND CGI.REQUEST_METHOD EQ "GET") {
|
||||
// доля времени, после которой происходит рефреш, прибита гвоздями
|
||||
// По всей видимости, рефреш будет ломать обращения POSТ
|
||||
// В связи с чем предлагается дождаться GET
|
||||
// Приклеивать query_string как-то не пришлось, браузер сам справляется
|
||||
|
||||
// refresh
|
||||
var idp = new lib.oauth2(this.client_id, this.client_secret, this.auth_endpoint, this.access_token_endpoint, this.redirect_uri);
|
||||
var resp = idp.refreshAccessTokenRequest(request.auth.refresh_token);
|
||||
|
||||
lock scope="application" type="readonly" timeout="1" {
|
||||
idpCertificate = application.idpCertificate;
|
||||
}
|
||||
|
||||
var auth = parseIdpresponse(resp, idpCertificate, this.client_secret); //все эти сложности из-за опасений насчет многопоточности и блокировок
|
||||
|
||||
lock scope="session" type="exclusive" timeout="1" {
|
||||
session.auth = auth;
|
||||
}
|
||||
request.auth = auth;
|
||||
writeDump(auth);
|
||||
}
|
||||
} else {
|
||||
// сессии SSO нет
|
||||
// или токен протух
|
||||
request.auth_state = createGUID().toString();
|
||||
lock scope="session" type="exclusive" timeout="1" {
|
||||
structDelete(session, "auth"); // зачистили сессию от данных SSO
|
||||
session.auth_state = request.auth_state;
|
||||
}
|
||||
|
||||
var idp = new lib.oauth2(this.client_id, this.client_secret, this.auth_endpoint, this.access_token_endpoint, this.redirect_uri);
|
||||
/*
|
||||
часто появляется ошибка: после неудачного запроса к IDP
|
||||
в адресной строке браузера остается все, с чем его редиректил IDP,
|
||||
@@ -195,67 +309,54 @@
|
||||
Не очень понятно, как предотвратить повторный запрос (можно, конечно, использовать сессию, но странно)
|
||||
*/
|
||||
//writeOutput(getTickCount()-request.startTickCount);
|
||||
if(structKeyExists(url, "code")) { //обрабатываем редирект от IDP *** наличие поля code в URL введет нас в заблуждение, но эvar = data, label =то только без валидной сессии
|
||||
//dump(var = url.code, label = "URL.code");
|
||||
// Request access token from idp with the
|
||||
// authorization code that we got via the URL
|
||||
//aFormFields = [];
|
||||
//data = idp.makeAccessTokenRequest((url.code).content, aFormFields);
|
||||
if(structKeyExists(url, "code")) { //обрабатываем редирект от IDP *** наличие поля code в URL введет нас в заблуждение,
|
||||
|
||||
try {
|
||||
writeOutput("idp.makeAccessTokenRequest");
|
||||
writeOutput(getTickCount()-request.startTickCount);
|
||||
resp = idp.makeAccessTokenRequest(url.code/*, aFormFields*/);
|
||||
writeOutput("idp.makeAccessTokenRequest Done");
|
||||
writeOutput(getTickCount()-request.startTickCount);
|
||||
//dump(resp);
|
||||
data = deserializeJson(resp.content);
|
||||
//writedump(data);
|
||||
// Print full response from idp
|
||||
//dump(var = data, label = "makeAccessTokenRequest - Response from idp");
|
||||
//writeOutput("idp.makeAccessTokenRequest");
|
||||
//writeOutput(getTickCount()-request.startTickCount);
|
||||
var resp = idp.makeAccessTokenRequest(url.code);
|
||||
|
||||
//echo('<a href="./index.cfm?refresh=#data.refresh_token#">Refresh token #data.refresh_token#</a>');
|
||||
|
||||
session.auth.expires_in = data.expires_in;
|
||||
session.auth.refresh_expires_in = data.refresh_expires_in;
|
||||
session.auth.access_token = data.access_token;
|
||||
session.auth.refresh_token = data.refresh_token;
|
||||
session.auth.id_token = data.id_token;
|
||||
session.auth.token_type = data.token_type;
|
||||
session.idp_response_content = structCopy(data);
|
||||
|
||||
//flush()
|
||||
lock scope="application" type="readonly" timeout="1" {
|
||||
token_data = (jwt.decode(data.access_token, application.idpCertificate,"RS256"));
|
||||
idpCertificate = application.idpCertificate;
|
||||
}
|
||||
writeOutput("jwt.decode Done");
|
||||
writeOutput(getTickCount()-request.startTickCount);
|
||||
writedump(token_data);
|
||||
session.auth.login = token_data.preferred_username;
|
||||
session.auth.wz = token_data.ClientID;
|
||||
session.auth.fullname = token_data.name;
|
||||
session.auth.groups = token_data.groups;
|
||||
session.auth.session_state = token_data.session_state;
|
||||
session.auth.sid = token_data.sid;
|
||||
session.auth.auth_time = token_data.auth_time;
|
||||
session.auth.exp = token_data.exp;
|
||||
session.auth.iat = token_data.iat;
|
||||
//session.sid = token_data.sid;
|
||||
session.token_data = structCopy(token_data);
|
||||
|
||||
location(this.redirect_uri,false);
|
||||
} catch (e) {echo('<br>****************** #e.message# : #e.detail# **********');}
|
||||
var auth = parseIdpresponse(resp, idpCertificate, this.client_secret); //все эти сложности из-за опасений насчет многопоточности и блокировок
|
||||
|
||||
} else {
|
||||
strURL = idp.buildRedirectToAuthURL({"scope":'openid profile email',"state":session.auth_state,"allow_signup":false});
|
||||
lock scope="session" type="exclusive" timeout="1" {
|
||||
session.auth = auth;
|
||||
}
|
||||
//request.auth = auth;
|
||||
location(this.redirect_uri, false);
|
||||
} catch (e) {echo('<br>****************** #e.message# : #e.detail# **************');}
|
||||
|
||||
} else { //отправляем браузер к IDP
|
||||
var strURL =idp.buildRedirectToAuthURL({"scope":'openid profile email',"state":request.auth_state,"allow_signup":false});
|
||||
echo('<a href="#strURL#">self-made Auth link (idp) #strURL#</a> <br> <br>');
|
||||
location(strUrl,false);
|
||||
}
|
||||
</cfscript>
|
||||
</cfif>
|
||||
|
||||
</cflock><!--- session exclusive --->
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//request.logout_url = "";
|
||||
if (structKeyExists(request, "auth") AND structKeyExists(request.auth, "id_token")) {
|
||||
request.logout_url = "#this.logout_endpoint#?id_token_hint=#request.auth.id_token#&post_logout_redirect_uri=#this.redirect_uri#?logout";
|
||||
// внимание, здесь подразумевается, что redirect_uri не содержит query_string
|
||||
// после возвращения от IDP нам нужно будет зачистить сессию SSO, сделаем это по слову logout
|
||||
}
|
||||
|
||||
//request.auth.wz='WZ01348'; //*******************
|
||||
//request.auth.wz='WZ01005'; //*******************
|
||||
//request.auth.wz='WZ01653'; //*******************
|
||||
//request.auth.wz='WZ02319'; //*******************
|
||||
//request.auth.wz='WZ01762'; //*******************
|
||||
//writedump(request.auth);abort;
|
||||
//********************
|
||||
//костыль
|
||||
if (structKeyExists(URL,"wz")) { request.auth.wz=URL.wz }
|
||||
//*********************
|
||||
</cfscript>
|
||||
|
||||
|
||||
<cfif structKeyExists(request, "auth")>
|
||||
@@ -334,7 +435,7 @@
|
||||
</cffunction>
|
||||
|
||||
|
||||
<cffunction
|
||||
<cffunction
|
||||
name="getDS"
|
||||
access="private"
|
||||
returntype="void"
|
||||
@@ -384,39 +485,116 @@
|
||||
<cfreturn/>
|
||||
</cffunction>
|
||||
|
||||
<cfscript>
|
||||
//https://keycloak.nubes.ru/admin
|
||||
//https://keycloak.nubes.ru/realms/SSH_CA/account //smishchuk@mgmt.nubes.ru
|
||||
//https://stackoverflow.com/questions/28658735/what-are-keycloaks-oauth2-openid-connect-endpoints
|
||||
//http://https://keycloak.nubes.ru/realms/SSH_CA/.well-known/openid-configuration
|
||||
<cfscript>
|
||||
//https://keycloak.nubes.ru/admin
|
||||
//https://keycloak.nubes.ru/realms/SSH_CA/account //smishchuk@mgmt.nubes.ru
|
||||
//https://stackoverflow.com/questions/28658735/what-are-keycloaks-oauth2-openid-connect-endpoints
|
||||
//http://https://keycloak.nubes.ru/realms/SSH_CA/.well-known/openid-configuration
|
||||
|
||||
//https://keycloak.nubes.ru/realms/cloud/.well-known/openid-configuration тут ссылка
|
||||
//https://keycloak.nubes.ru/realms/cloud/protocol/openid-connect/certs тут серт
|
||||
//только надо его обрамить -----BEGIN CERTIFICATE-----
|
||||
function getIdpCertificate(certUrl) {
|
||||
//https://keycloak.nubes.ru/realms/cloud/.well-known/openid-configuration тут ссылка
|
||||
//https://keycloak.nubes.ru/realms/cloud/protocol/openid-connect/certs тут серт
|
||||
//только надо его обрамить -----BEGIN CERTIFICATE-----
|
||||
private function getIdpCertificate(certUrl) {
|
||||
|
||||
var httpService = new http();
|
||||
httpService.setMethod( "get" );
|
||||
httpService.setCharset( "utf-8" );
|
||||
httpService.setUrl(arguments.certUrl);
|
||||
var httpService = new http();
|
||||
httpService.setMethod( "get" );
|
||||
httpService.setCharset( "utf-8" );
|
||||
httpService.setUrl(arguments.certUrl);
|
||||
|
||||
var result = httpService.send().getPrefix();
|
||||
var status_code = result.ResponseHeader['Status_Code'];
|
||||
var result = httpService.send().getPrefix();
|
||||
var status_code = result.ResponseHeader['Status_Code'];
|
||||
|
||||
if ('200' == status_code) {
|
||||
var content = deserializeJson(result.FileContent);
|
||||
//мы подразумеваем структуру конкретно KeyCloak
|
||||
var key = "";
|
||||
for (key in content.keys) {
|
||||
if ("RSA" == key.kty AND "sig" == key.use) {
|
||||
return "-----BEGIN CERTIFICATE-----" & key.x5c[1] & "-----END CERTIFICATE-----";
|
||||
if ('200' == status_code) {
|
||||
var content = deserializeJson(result.FileContent);
|
||||
//мы подразумеваем структуру конкретно KeyCloak
|
||||
var key = "";
|
||||
for (key in content.keys) {
|
||||
if ("RSA" == key.kty AND "sig" == key.use) {
|
||||
return "-----BEGIN CERTIFICATE-----" & key.x5c[1] & "-----END CERTIFICATE-----";
|
||||
}
|
||||
}
|
||||
throw(message="RSA cetificate not found");
|
||||
} else {
|
||||
throw (message="Cannot obtain IDP certificate, request failed", detail="Status_Code #status_code#");
|
||||
}
|
||||
throw(message="RSA cetificate not found");
|
||||
} else {
|
||||
throw (message="Cannot obtain IDP certificate, request failed", detail="Status_Code #status_code#");
|
||||
}
|
||||
}
|
||||
|
||||
</cfscript>
|
||||
private struct function parseIdpResponse(struct resp, string certificate, string jwt_secret) {
|
||||
|
||||
var auth = structNew("linked");
|
||||
var data = deserializeJson(arguments.resp.content);
|
||||
var jwt = new lib.jwt(arguments.jwt_secret);
|
||||
|
||||
auth.expires_in = data.expires_in;
|
||||
auth.refresh_expires_in = data.refresh_expires_in;
|
||||
auth.access_token = data.access_token;
|
||||
auth.refresh_token = data.refresh_token;
|
||||
auth.id_token = data.id_token;
|
||||
auth.token_type = data.token_type;
|
||||
|
||||
//idp_response_content = structCopy(data); //for debug
|
||||
var token_data = (jwt.decode(data.access_token, arguments.certificate,"RS256"));
|
||||
|
||||
auth.session_state = token_data.session_state;
|
||||
auth.sid = token_data.sid;
|
||||
auth.auth_time = token_data.auth_time;
|
||||
auth.exp = token_data.exp;
|
||||
auth.iat = token_data.iat;
|
||||
|
||||
auth.login = token_data.preferred_username;
|
||||
auth.wz = token_data.ClientID;
|
||||
auth.fullname = token_data.name;
|
||||
auth.groups = token_data.groups;
|
||||
//auth.token_data = structCopy(token_data); //for debug
|
||||
|
||||
return (auth);
|
||||
}
|
||||
|
||||
</cfscript>
|
||||
|
||||
<cffunction name="rethrow" returntype="void">
|
||||
<!--- https://www.raymondcamden.com/2004/03/09/3089633C-9FA0-606B-3F540AE9642A795F --->
|
||||
<cftry>
|
||||
<cfcatch>
|
||||
<cfrethrow/>
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
<cfthrow type="Context validation error" message="RETHROW() called outside TRY-CATCH"/>
|
||||
</cffunction>
|
||||
|
||||
<!--- как определить стенд? Из персистенса. Из окружения --->
|
||||
|
||||
<!--- <cffunction name="locateIamService"><!--- *** архитектурный колхоз --->
|
||||
<!--- почему-то мы не видим других функций, когда нас вызывают onApplicationStart. С другой стороны, а почему вообще должны вызывать без перезагрузки приложения --->
|
||||
<cfset var stand=""/>
|
||||
<!--- дублируем код, потому что getStand отсюда почему-то не виден --->
|
||||
<cftry>
|
||||
<cfquery name=qConfig>
|
||||
select value as stand from config
|
||||
where name='STAND'
|
||||
</cfquery>
|
||||
<cfset stand = qConfig.stand/>
|
||||
|
||||
<cfswitch expression=#stand#>
|
||||
<cfcase value=",dev">
|
||||
<cfreturn "https://auth-api-dev.ngcloud.ru/api/v1" />
|
||||
</cfcase>
|
||||
<cfcase value="test">
|
||||
<cfreturn "https://auth-api-test.ngcloud.ru/api/v1" />
|
||||
</cfcase>
|
||||
<cfcase value="prod">
|
||||
<cfreturn "https://auth-api.ngcloud.ru/api/v1" />
|
||||
</cfcase>
|
||||
<cfdefaultcase><!--- proceed to the legacy locator ---></cfdefaultcase>
|
||||
</cfswitch>
|
||||
|
||||
<cfcatch type="ANY">
|
||||
<!--- do nothing, proceed to the legacy locator --->
|
||||
<cfrethrow/>
|
||||
<cfthrow message="IAM service unavailable" detail="there is no IAM for stand #stand# defined"/>
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
|
||||
</cffunction> --->
|
||||
|
||||
</cfcomponent>
|
||||
@@ -0,0 +1,6 @@
|
||||
корректный период
|
||||
другие WZ
|
||||
? full join
|
||||
детализация - для S3 это бакеты
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
pvdc_map(pvdc,code) as (VALUES
|
||||
('v1cl1-vsan-pvdc',''),
|
||||
('v1cl2-pvdc',''),
|
||||
('v2cl2-1c-pvdc',''),
|
||||
('v1cl4-vsan-pvdc',''),
|
||||
('v1cl6-vsan-pvdc',''),
|
||||
('v1cl7-vsan-pvdc',''),
|
||||
('hystax-pvdc',''),
|
||||
('','')
|
||||
)
|
||||
@@ -0,0 +1,205 @@
|
||||
DROP FOREIGN TABLE IF EXISTS vmreports.compute CASCADE;
|
||||
DROP FOREIGN TABLE IF EXISTS vmreports.storage CASCADE;
|
||||
DROP FOREIGN TABLE IF EXISTS vmreports.host CASCADE;
|
||||
DROP FOREIGN TABLE IF EXISTS vmreports.vm_gpu CASCADE;
|
||||
DROP FOREIGN TABLE IF EXISTS vmreports.vm_power_state CASCADE;
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
CREATE SCHEMA IF NOT EXISTS vmreports;
|
||||
ALTER SCHEMA vmreports OWNER TO dbo;
|
||||
GRANT USAGE ON SCHEMA vmreports TO nifi,appserver,reader,analytics,analyst;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT SELECT ON TABLES TO appserver,reader;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT SELECT, REFERENCES ON TABLES TO appserver,analytics,analyst;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT ALL ON TABLES TO nifi;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT USAGE ON SEQUENCES TO nifi, appserver;
|
||||
|
||||
SET default_tablespace = '';
|
||||
|
||||
SET default_table_access_method = heap;
|
||||
|
||||
--
|
||||
-- TOC entry 721 (class 1259 OID 9816992)
|
||||
-- Name: compute; Type: TABLE; Schema: vmreports; Owner: smishchuk
|
||||
--
|
||||
|
||||
CREATE TABLE vmreports.compute (
|
||||
"Name" character varying(255),
|
||||
"UUID_VM" character varying(255),
|
||||
"VDC" character varying(255),
|
||||
"Organization_UUID" uuid,
|
||||
"Organization" character varying(255),
|
||||
"WZ" character varying(255),
|
||||
"Cluster" character varying(255),
|
||||
"Host" character varying(255),
|
||||
"Host_Model" character varying(255),
|
||||
"CPU_Model" character varying(255),
|
||||
"Host_CPU_Cores" double precision,
|
||||
"Host_CPU_Sockets" double precision,
|
||||
"Host_CPU_Speed" double precision,
|
||||
"Host_RAM" double precision,
|
||||
"Host_CPU_Used" double precision,
|
||||
"Host_CPU_Used_Avg" double precision,
|
||||
"VDC_CPU_Reserv" double precision,
|
||||
"VDC_CPU_Speed" double precision,
|
||||
"VM_vCPU_count" double precision,
|
||||
"VM_CPU_Used" double precision,
|
||||
"VM_CPU_Used_AVG" double precision,
|
||||
"VM_CPU_Reserv_GHz" double precision,
|
||||
"VM_CPU_Reserv_perc" double precision,
|
||||
"VM_RAM_Allocated" double precision,
|
||||
"VM_RAM_Used" double precision,
|
||||
"VM_is_ON" double precision,
|
||||
"Object_UUID" uuid NOT NULL,
|
||||
ts timestamp with time zone NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE vmreports.compute OWNER TO dbo;
|
||||
|
||||
--
|
||||
-- TOC entry 722 (class 1259 OID 9817004)
|
||||
-- Name: storage; Type: TABLE; Schema: vmreports; Owner: smishchuk
|
||||
--
|
||||
|
||||
CREATE TABLE vmreports.storage (
|
||||
"Name" character varying(255),
|
||||
"VM_UUID" character varying(255),
|
||||
"VDC" character varying(255),
|
||||
"Organization_UUID" uuid,
|
||||
"Organization" character varying(255),
|
||||
"WZ" character varying(255),
|
||||
"Cluster" character varying(255),
|
||||
"Disk" character varying(255),
|
||||
"Storage_Policy" character varying(255),
|
||||
"Disk_Allocated" double precision,
|
||||
"Disk_Used" double precision,
|
||||
"VM_is_ON" double precision,
|
||||
"Object_UUID" uuid NOT NULL,
|
||||
ts timestamp with time zone NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE vmreports.storage OWNER TO dbo;
|
||||
|
||||
--
|
||||
-- TOC entry 720 (class 1259 OID 9816984)
|
||||
-- Name: host; Type: TABLE; Schema: vmreports; Owner: smishchuk
|
||||
--
|
||||
|
||||
CREATE TABLE vmreports.host (
|
||||
"Name" character varying(255),
|
||||
"Model" character varying(255),
|
||||
"Cluster" character varying(255),
|
||||
"Maintenance" character varying(255),
|
||||
"CPU_Cores" double precision,
|
||||
"CPU_Sockets" double precision,
|
||||
"CPU_Speed" double precision,
|
||||
"RAM_Total" double precision,
|
||||
"RAM_Used" double precision,
|
||||
"CPU_Used" double precision,
|
||||
"CPU_Used_AVG" double precision,
|
||||
"CPU_Contention_95" double precision,
|
||||
"Object_UUID" uuid NOT NULL,
|
||||
ts timestamp with time zone NOT NULL,
|
||||
"Cluster_v2" character varying(255),
|
||||
"HT_Active" boolean,
|
||||
"CPUtoVM" double precision,
|
||||
"RAMtoVM" double precision
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE vmreports.host OWNER TO dbo;
|
||||
|
||||
--
|
||||
-- TOC entry 733 (class 1259 OID 11093092)
|
||||
-- Name: vm_gpu; Type: TABLE; Schema: vmreports; Owner: smishchuk
|
||||
--
|
||||
|
||||
CREATE TABLE vmreports.vm_gpu (
|
||||
"Name" character varying(255),
|
||||
"ClientID" character varying(255),
|
||||
"VCD" character varying(255),
|
||||
"Org" character varying(255),
|
||||
"OrgVDC" character varying(255),
|
||||
"vCenter" character varying(255),
|
||||
"GPU" jsonb,
|
||||
"OrgStatus" character varying(255),
|
||||
"Object_UUID" uuid NOT NULL,
|
||||
ts timestamp with time zone NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE vmreports.vm_gpu OWNER TO dbo;
|
||||
|
||||
--
|
||||
-- TOC entry 732 (class 1259 OID 11093087)
|
||||
-- Name: vm_power_state; Type: TABLE; Schema: vmreports; Owner: smishchuk
|
||||
--
|
||||
|
||||
CREATE TABLE vmreports.vm_power_state (
|
||||
"Object_UUID" uuid NOT NULL,
|
||||
ts timestamp with time zone NOT NULL,
|
||||
value double precision
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE vmreports.vm_power_state OWNER TO dbo;
|
||||
|
||||
--
|
||||
-- TOC entry 4761 (class 2606 OID 9816998)
|
||||
-- Name: compute pk_compute; Type: CONSTRAINT; Schema: vmreports; Owner: smishchuk
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY vmreports.compute
|
||||
ADD CONSTRAINT pk_compute PRIMARY KEY (ts, "Object_UUID");
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 4759 (class 2606 OID 9816990)
|
||||
-- Name: host pk_host; Type: CONSTRAINT; Schema: vmreports; Owner: smishchuk
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY vmreports.host
|
||||
ADD CONSTRAINT pk_host PRIMARY KEY (ts, "Object_UUID");
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 4763 (class 2606 OID 9817010)
|
||||
-- Name: storage pk_storage; Type: CONSTRAINT; Schema: vmreports; Owner: smishchuk
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY vmreports.storage
|
||||
ADD CONSTRAINT pk_storage PRIMARY KEY (ts, "Object_UUID");
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 4767 (class 2606 OID 11093098)
|
||||
-- Name: vm_gpu pk_vm_gpu; Type: CONSTRAINT; Schema: vmreports; Owner: smishchuk
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY vmreports.vm_gpu
|
||||
ADD CONSTRAINT pk_vm_gpu PRIMARY KEY (ts, "Object_UUID");
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 4765 (class 2606 OID 11093091)
|
||||
-- Name: vm_power_state pk_vm_power_state; Type: CONSTRAINT; Schema: vmreports; Owner: smishchuk
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY vmreports.vm_power_state
|
||||
ADD CONSTRAINT pk_vm_power_state PRIMARY KEY ("Object_UUID", ts);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 5168 (class 0 OID 0)
|
||||
-- Dependencies: 10
|
||||
-- Name: SCHEMA vmreports; Type: ACL; Schema: -; Owner: dbo
|
||||
--
|
||||
|
||||
GRANT ALL ON SCHEMA vmreports TO nifi;
|
||||
|
||||
|
||||
|
||||
GRANT ALL ON ALL TABLES IN SCHEMA vmreports TO nifi;
|
||||
GRANT SELECT, REFERENCES ON ALL TABLES IN SCHEMA vmreports TO analytics, analyst;
|
||||
@@ -0,0 +1,595 @@
|
||||
база rpt сделана из базы billing (название изменено, чтобы избежать путаницы)
|
||||
-- удалены последовательности, переназначены владельцы и права
|
||||
-- удалены внешние ключи
|
||||
|
||||
-- создать роль dbo (владелец), без connect
|
||||
-- создать пользователя nifi, с правом логина
|
||||
-- создать пользователя appserver, с правом логина
|
||||
-- дать права пользователю nifi на схемы и таблицы
|
||||
-- дать права пользователю appserver на схемы и таблицы на чтение
|
||||
|
||||
SET ROLE postgres;
|
||||
|
||||
CREATE SCHEMA IF NOT EXISTS s3billing;
|
||||
CREATE SCHEMA IF NOT EXISTS ngcloud_ru;
|
||||
|
||||
ALTER SCHEMA s3billing OWNER TO dbo;
|
||||
ALTER SCHEMA ngcloud_ru OWNER TO dbo;
|
||||
ALTER DATABASE rpt SET search_path TO s3billing, ngcloud_ru;
|
||||
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo, postgres GRANT ALL ON TABLES TO nifi;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo, postgres GRANT SELECT ON TABLES TO appserver;
|
||||
|
||||
SET ROLE dbo;
|
||||
|
||||
GRANT USAGE ON SCHEMA s3billing TO appserver,nifi;
|
||||
GRANT USAGE ON SCHEMA ngcloud_ru TO appserver,nifi;
|
||||
|
||||
GRANT ALL ON ALL TABLES IN SCHEMA s3billing TO nifi;
|
||||
GRANT SELECT ON ALL TABLES IN SCHEMA s3billing TO appserver;
|
||||
|
||||
GRANT ALL ON ALL TABLES IN SCHEMA ngcloud_ru TO nifi;
|
||||
GRANT SELECT ON ALL TABLES IN SCHEMA ngcloud_ru TO appserver;
|
||||
|
||||
--GRANT ALL ON ALL SEQUENCES IN SCHEMA s3billing TO appserver,nifi;
|
||||
--GRANT ALL ON ALL SEQUENCES IN SCHEMA ngcloud_ru TO appserver,nifi;
|
||||
|
||||
|
||||
--ALTER DEFAULT PRIVILEGES FOR ROLE dbo GRANT ALL ON SEQUENCES TO appserver,nifi;
|
||||
|
||||
--
|
||||
-- PostgreSQL database dump
|
||||
--
|
||||
|
||||
-- Dumped from database version 16.0
|
||||
-- Dumped by pg_dump version 16.4
|
||||
|
||||
-- Started on 2025-09-15 09:50:58
|
||||
|
||||
SET statement_timeout = 0;
|
||||
SET lock_timeout = 0;
|
||||
SET idle_in_transaction_session_timeout = 0;
|
||||
SET client_encoding = 'UTF8';
|
||||
SET standard_conforming_strings = on;
|
||||
SELECT pg_catalog.set_config('search_path', '', false);
|
||||
SET check_function_bodies = false;
|
||||
SET xmloption = content;
|
||||
SET client_min_messages = warning;
|
||||
SET row_security = off;
|
||||
|
||||
SET default_tablespace = '';
|
||||
|
||||
SET default_table_access_method = heap;
|
||||
|
||||
--
|
||||
-- TOC entry 230 (class 1259 OID 2160668)
|
||||
-- Name: bucket_info; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS s3billing.bucket_info;
|
||||
CREATE TABLE s3billing.bucket_info (
|
||||
id integer NOT NULL,
|
||||
bucket_id character varying(255) NOT NULL,
|
||||
name character varying(255) NOT NULL,
|
||||
marker character varying(255) NOT NULL,
|
||||
placement_id bigint DEFAULT 0 NOT NULL
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 226 (class 1259 OID 2160642)
|
||||
-- Name: bucket_stat; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
DROP TABLE IF EXISTS s3billing.bucket_stat;
|
||||
CREATE TABLE s3billing.bucket_stat (
|
||||
bucket_id bigint,
|
||||
num_shards bigint NOT NULL,
|
||||
tenant character varying(255) DEFAULT NULL::character varying,
|
||||
zone_group bigint NOT NULL,
|
||||
placement_id bigint NOT NULL,
|
||||
explicit_placement_data_pool character varying(255) DEFAULT NULL::character varying,
|
||||
explicit_placement_data_extra_pool character varying(255) DEFAULT NULL::character varying,
|
||||
explicit_placement_index_pool character varying(255) DEFAULT NULL::character varying,
|
||||
index_type_id bigint NOT NULL,
|
||||
versioned boolean DEFAULT false,
|
||||
versioning_enabled boolean DEFAULT false,
|
||||
object_lock_enabled boolean DEFAULT false,
|
||||
mfa_enabled boolean DEFAULT false,
|
||||
owner character varying(255) NOT NULL,
|
||||
bucket_quota_enabled boolean DEFAULT false,
|
||||
bucket_quota_check_on_raw boolean DEFAULT false,
|
||||
bucket_quota_max_size bigint NOT NULL,
|
||||
bucket_quota_max_size_kb bigint NOT NULL,
|
||||
bucket_quota_max_objects bigint NOT NULL,
|
||||
usage_rgw_main_size bigint NOT NULL,
|
||||
usage_rgw_main_size_actual bigint NOT NULL,
|
||||
usage_rgw_main_size_utilized bigint NOT NULL,
|
||||
usage_rgw_main_size_kb bigint NOT NULL,
|
||||
usage_rgw_main_size_kb_actual bigint NOT NULL,
|
||||
usage_rgw_main_size_kb_utilized bigint NOT NULL,
|
||||
usage_rgw_main_num_objects bigint NOT NULL,
|
||||
usage_rgw_multimeta_size bigint,
|
||||
usage_rgw_multimeta_size_actual bigint,
|
||||
usage_rgw_multimeta_size_utilized bigint,
|
||||
usage_rgw_multimeta_size_kb bigint,
|
||||
usage_rgw_multimeta_size_kb_actual bigint,
|
||||
usage_rgw_multimeta_size_kb_utilized bigint,
|
||||
usage_rgw_multimeta_num_objects bigint,
|
||||
creation_time timestamp without time zone NOT NULL,
|
||||
mtime timestamp without time zone NOT NULL,
|
||||
timestamp_addition timestamp without time zone DEFAULT date_trunc('hour'::text, CURRENT_TIMESTAMP)
|
||||
);
|
||||
|
||||
--
|
||||
-- TOC entry 245 (class 1259 OID 2160763)
|
||||
-- Name: category; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
DROP TABLE IF EXISTS s3billing.category;
|
||||
CREATE TABLE s3billing.category (
|
||||
id integer NOT NULL,
|
||||
name character varying(255) NOT NULL
|
||||
);
|
||||
|
||||
--
|
||||
-- TOC entry 225 (class 1259 OID 2160635)
|
||||
-- Name: goose_db_version; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
DROP TABLE IF EXISTS s3billing.goose_db_version;
|
||||
CREATE TABLE s3billing.goose_db_version (
|
||||
id integer NOT NULL,
|
||||
version_id bigint NOT NULL,
|
||||
is_applied boolean NOT NULL,
|
||||
tstamp timestamp without time zone DEFAULT now() NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 234 (class 1259 OID 2160684)
|
||||
-- Name: index_type; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
DROP TABLE IF EXISTS index_type;
|
||||
CREATE TABLE s3billing.index_type (
|
||||
id integer NOT NULL,
|
||||
name character varying(255) NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 232 (class 1259 OID 2160677)
|
||||
-- Name: placement; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
DROP TABLE IF EXISTS s3billing.placement;
|
||||
CREATE TABLE s3billing.placement (
|
||||
id integer NOT NULL,
|
||||
name character varying(255) NOT NULL
|
||||
);
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 239 (class 1259 OID 2160705)
|
||||
-- Name: usage_bucket_by_user; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
DROP TABLE IF EXISTS s3billing.usage_bucket_by_user;
|
||||
CREATE TABLE s3billing.usage_bucket_by_user (
|
||||
bucketid bigint,
|
||||
"time" timestamp without time zone NOT NULL,
|
||||
bytes_sent bigint NOT NULL,
|
||||
bytes_received bigint NOT NULL,
|
||||
ops bigint NOT NULL,
|
||||
successful_ops bigint NOT NULL,
|
||||
date_start timestamp without time zone NOT NULL,
|
||||
date_end timestamp without time zone NOT NULL,
|
||||
user_id bigint NOT NULL,
|
||||
category_id bigint NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 238 (class 1259 OID 2160698)
|
||||
-- Name: usage_stat_summary; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
DROP TABLE IF EXISTS s3billing.usage_stat_summary;
|
||||
CREATE TABLE s3billing.usage_stat_summary (
|
||||
id integer NOT NULL,
|
||||
userid character varying(255) NOT NULL,
|
||||
category character varying(255) NOT NULL,
|
||||
bytes_sent bigint NOT NULL,
|
||||
bytes_received bigint NOT NULL,
|
||||
ops bigint NOT NULL,
|
||||
successful_ops bigint NOT NULL,
|
||||
date_start timestamp without time zone NOT NULL,
|
||||
date_end timestamp without time zone NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 236 (class 1259 OID 2160691)
|
||||
-- Name: usage_stat_total; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
DROP TABLE IF EXISTS s3billing.usage_stat_total;
|
||||
CREATE TABLE s3billing.usage_stat_total (
|
||||
id integer NOT NULL,
|
||||
userid character varying(255) NOT NULL,
|
||||
bytes_sent bigint NOT NULL,
|
||||
bytes_received bigint NOT NULL,
|
||||
ops bigint NOT NULL,
|
||||
successful_ops bigint NOT NULL,
|
||||
date_start timestamp without time zone NOT NULL,
|
||||
date_end timestamp without time zone NOT NULL
|
||||
);
|
||||
|
||||
--
|
||||
-- TOC entry 243 (class 1259 OID 2160751)
|
||||
-- Name: user_info; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
DROP TABLE IF EXISTS s3billing.user_info;
|
||||
CREATE TABLE s3billing.user_info (
|
||||
id integer NOT NULL,
|
||||
name character varying(255) NOT NULL,
|
||||
owner character varying(255) NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 241 (class 1259 OID 2160712)
|
||||
-- Name: user_quota_bucket; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
DROP TABLE IF EXISTS s3billing.user_quota_bucket;
|
||||
CREATE TABLE s3billing.user_quota_bucket (
|
||||
id integer NOT NULL,
|
||||
userid character varying(255) NOT NULL,
|
||||
enabled boolean DEFAULT false,
|
||||
check_on_raw boolean DEFAULT false,
|
||||
max_size bigint NOT NULL,
|
||||
max_size_kb bigint NOT NULL,
|
||||
max_objects bigint NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 228 (class 1259 OID 2160661)
|
||||
-- Name: zone_group; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
DROP TABLE IF EXISTS s3billing.zone_group;
|
||||
CREATE TABLE s3billing.zone_group (
|
||||
id integer NOT NULL,
|
||||
name uuid NOT NULL
|
||||
);
|
||||
|
||||
--
|
||||
-- TOC entry 3278 (class 2606 OID 2160675)
|
||||
-- Name: bucket_info bucket_info_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.bucket_info
|
||||
ADD CONSTRAINT bucket_info_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3273 (class 2606 OID 2476484)
|
||||
-- Name: bucket_stat bucket_stat_unique; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
--ALTER TABLE ONLY s3billing.bucket_stat
|
||||
-- ADD CONSTRAINT bucket_stat_unique UNIQUE (bucket_id, placement_id, timestamp_addition);
|
||||
|
||||
ALTER TABLE ONLY s3billing.bucket_stat
|
||||
ADD CONSTRAINT bucket_stat_pkey PRIMARY KEY (bucket_id, placement_id, timestamp_addition);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3298 (class 2606 OID 2160768)
|
||||
-- Name: category category_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.category
|
||||
ADD CONSTRAINT category_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3270 (class 2606 OID 2160640)
|
||||
-- Name: goose_db_version goose_db_version_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.goose_db_version
|
||||
ADD CONSTRAINT goose_db_version_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3284 (class 2606 OID 2160689)
|
||||
-- Name: index_type index_type_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.index_type
|
||||
ADD CONSTRAINT index_type_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3282 (class 2606 OID 2160682)
|
||||
-- Name: placement placement_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.placement
|
||||
ADD CONSTRAINT placement_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3290 (class 2606 OID 2476705)
|
||||
-- Name: usage_bucket_by_user usage_bucket_by_user_unique; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
--ALTER TABLE ONLY s3billing.usage_bucket_by_user
|
||||
-- ADD CONSTRAINT usage_bucket_by_user_unique UNIQUE (bucketid, date_start, date_end, user_id, category_id);
|
||||
ALTER TABLE ONLY s3billing.usage_bucket_by_user
|
||||
ADD CONSTRAINT usage_bucket_by_user_pkey PRIMARY KEY (bucketid, date_start, date_end, user_id, category_id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3288 (class 2606 OID 2160703)
|
||||
-- Name: usage_stat_summary usage_stat_summary_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.usage_stat_summary
|
||||
ADD CONSTRAINT usage_stat_summary_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3286 (class 2606 OID 2160696)
|
||||
-- Name: usage_stat_total usage_stat_total_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.usage_stat_total
|
||||
ADD CONSTRAINT usage_stat_total_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3295 (class 2606 OID 2160758)
|
||||
-- Name: user_info user_info_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.user_info
|
||||
ADD CONSTRAINT user_info_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3292 (class 2606 OID 2160719)
|
||||
-- Name: user_quota_bucket user_quota_bucket_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.user_quota_bucket
|
||||
ADD CONSTRAINT user_quota_bucket_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3275 (class 2606 OID 2160666)
|
||||
-- Name: zone_group zone_group_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.zone_group
|
||||
ADD CONSTRAINT zone_group_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3276 (class 1259 OID 2474077)
|
||||
-- Name: bucket_info_name_idx; Type: INDEX; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE INDEX bucket_info_name_idx ON s3billing.bucket_info USING btree (name);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3279 (class 1259 OID 2474078)
|
||||
-- Name: bucket_info_placement_id_idx; Type: INDEX; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE INDEX bucket_info_placement_id_idx ON s3billing.bucket_info USING btree (placement_id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3271 (class 1259 OID 2474094)
|
||||
-- Name: bucket_stat_owner_idx; Type: INDEX; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE INDEX bucket_stat_owner_idx ON s3billing.bucket_stat USING btree (owner);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3296 (class 1259 OID 2474445)
|
||||
-- Name: category_name_idx; Type: INDEX; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX category_name_idx ON s3billing.category USING btree (name);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3280 (class 1259 OID 2474468)
|
||||
-- Name: placement_name_idx; Type: INDEX; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX placement_name_idx ON s3billing.placement USING btree (name);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3293 (class 1259 OID 2474438)
|
||||
-- Name: user_info_name_idx; Type: INDEX; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE INDEX user_info_name_idx ON s3billing.user_info USING btree (name);
|
||||
|
||||
|
||||
|
||||
-- Completed on 2025-09-15 09:50:59
|
||||
|
||||
--
|
||||
-- PostgreSQL database dump complete
|
||||
--
|
||||
|
||||
-------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------
|
||||
|
||||
DROP TABLE IF EXISTS ngcloud_ru.capacity_resource;
|
||||
CREATE TABLE ngcloud_ru.capacity_resource (
|
||||
vdc_id uuid NOT NULL,
|
||||
"timestamp" timestamp with time zone NOT NULL,
|
||||
cpu_allocated integer NOT NULL,
|
||||
cpu_limit integer NOT NULL,
|
||||
cpu_reserved integer NOT NULL,
|
||||
cpu_used integer NOT NULL,
|
||||
cpu_speed integer NOT NULL,
|
||||
mem_allocated integer NOT NULL,
|
||||
mem_limit integer NOT NULL,
|
||||
mem_reserved integer NOT NULL,
|
||||
mem_used integer NOT NULL
|
||||
);
|
||||
|
||||
--
|
||||
-- TOC entry 223 (class 1259 OID 1893993)
|
||||
-- Name: capacity_storage; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
DROP TABLE IF EXISTS ngcloud_ru.capacity_storage;
|
||||
CREATE TABLE ngcloud_ru.capacity_storage (
|
||||
vdc_id uuid NOT NULL,
|
||||
storage_profile_types_id integer NOT NULL,
|
||||
"timestamp" timestamp with time zone NOT NULL,
|
||||
id uuid NOT NULL,
|
||||
"limit" integer NOT NULL,
|
||||
used integer NOT NULL
|
||||
);
|
||||
|
||||
--
|
||||
-- TOC entry 220 (class 1259 OID 1893965)
|
||||
-- Name: storage_profile_types; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
DROP TABLE IF EXISTS ngcloud_ru.storage_profile_types;
|
||||
CREATE TABLE ngcloud_ru.storage_profile_types (
|
||||
id integer NOT NULL,
|
||||
name character varying(255) NOT NULL
|
||||
);
|
||||
|
||||
--
|
||||
-- TOC entry 218 (class 1259 OID 1893959)
|
||||
-- Name: tenant; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
DROP TABLE IF EXISTS ngcloud_ru.tenant;
|
||||
CREATE TABLE ngcloud_ru.tenant (
|
||||
id uuid NOT NULL,
|
||||
name character varying(255) NOT NULL,
|
||||
wzcode bigint
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 221 (class 1259 OID 1893973)
|
||||
-- Name: vdc; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
DROP TABLE IF EXISTS ngcloud_ru.vdc;
|
||||
CREATE TABLE ngcloud_ru.vdc (
|
||||
id uuid NOT NULL,
|
||||
tenant_id uuid NOT NULL,
|
||||
name character varying(255) NOT NULL
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3255 (class 2606 OID 1893987)
|
||||
-- Name: capacity_resource capacity_resource_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY ngcloud_ru.capacity_resource
|
||||
ADD CONSTRAINT capacity_resource_pkey PRIMARY KEY (vdc_id, "timestamp");
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3257 (class 2606 OID 1893997)
|
||||
-- Name: capacity_storage capacity_storage_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY ngcloud_ru.capacity_storage
|
||||
ADD CONSTRAINT capacity_storage_pkey PRIMARY KEY (vdc_id, id, "timestamp");
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3249 (class 2606 OID 1893972)
|
||||
-- Name: storage_profile_types storage_profile_types_name_key; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY ngcloud_ru.storage_profile_types
|
||||
ADD CONSTRAINT storage_profile_types_name_key UNIQUE (name);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3251 (class 2606 OID 1893970)
|
||||
-- Name: storage_profile_types storage_profile_types_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY ngcloud_ru.storage_profile_types
|
||||
ADD CONSTRAINT storage_profile_types_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3247 (class 2606 OID 1893963)
|
||||
-- Name: tenant tenant_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY ngcloud_ru.tenant
|
||||
ADD CONSTRAINT tenant_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3253 (class 2606 OID 1893977)
|
||||
-- Name: vdc vdc_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY ngcloud_ru.vdc
|
||||
ADD CONSTRAINT vdc_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3259 (class 2606 OID 1893988)
|
||||
-- Name: capacity_resource capacity_resource_vdc_id_fkey; Type: FK CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
--ALTER TABLE ONLY ngcloud_ru.capacity_resource
|
||||
-- ADD CONSTRAINT capacity_resource_vdc_id_fkey FOREIGN KEY (vdc_id) REFERENCES ngcloud_ru.vdc(id) ON DELETE CASCADE;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3260 (class 2606 OID 1894003)
|
||||
-- Name: capacity_storage capacity_storage_storage_profile_types_id_fkey; Type: FK CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
--ALTER TABLE ONLY ngcloud_ru.capacity_storage
|
||||
-- ADD CONSTRAINT capacity_storage_storage_profile_types_id_fkey FOREIGN KEY (storage_profile_types_id) REFERENCES ngcloud_ru.storage_profile_types(id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3261 (class 2606 OID 1893998)
|
||||
-- Name: capacity_storage capacity_storage_vdc_id_fkey; Type: FK CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
--ALTER TABLE ONLY ngcloud_ru.capacity_storage
|
||||
-- ADD CONSTRAINT capacity_storage_vdc_id_fkey FOREIGN KEY (vdc_id) REFERENCES ngcloud_ru.vdc(id) ON DELETE CASCADE;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3258 (class 2606 OID 1893978)
|
||||
-- Name: vdc vdc_tenant_id_fkey; Type: FK CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
--ALTER TABLE ONLY ngcloud_ru.vdc
|
||||
-- ADD CONSTRAINT vdc_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES ngcloud_ru.tenant(id);
|
||||
|
||||
|
||||
-- Completed on 2025-09-15 09:53:18
|
||||
|
||||
--
|
||||
-- PostgreSQL database dump complete
|
||||
--
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,72 @@
|
||||
set role postgres;
|
||||
--
|
||||
CREATE SCHEMA IF NOT EXISTS gpu;
|
||||
--ALTER SCHEMA gpu OWNER TO dbo;
|
||||
GRANT USAGE ON SCHEMA gpu TO nifi;
|
||||
|
||||
GRANT ALL ON ALL TABLES IN SCHEMA gpu TO nifi;
|
||||
GRANT ALL ON ALL SEQUENCES IN SCHEMA gpu TO nifi;
|
||||
|
||||
--ALTER DEFAULT PRIVILEGES IN SCHEMA gpu GRANT ALL ON TABLES TO nifi;
|
||||
--ALTER DEFAULT PRIVILEGES IN SCHEMA gpu GRANT ALL ON SEQUENCES TO nifi;
|
||||
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo, postgres IN SCHEMA gpu GRANT ALL ON TABLES TO nifi;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo, postgres IN SCHEMA gpu GRANT ALL ON SEQUENCES TO nifi;
|
||||
|
||||
--SET ROLE dbo;
|
||||
|
||||
DROP TABLE IF EXISTS gpu.vm;
|
||||
CREATE TABLE gpu.vm (
|
||||
objUUID uuid NOT NULL PRIMARY KEY
|
||||
,groupUUID uuid NULL
|
||||
,objId varchar(255) NULL
|
||||
,ClientID varchar(255) NULL -- WZ
|
||||
,VCD varchar(255) NULL
|
||||
,Org varchar(255) NULL
|
||||
,OrgVDC varchar(255) NULL
|
||||
,vCenter varchar(255) NULL
|
||||
,GPU varchar(255) NULL
|
||||
,dt_load timestamptz NOT NULL
|
||||
);
|
||||
ALTER TABLE gpu.vm OWNER TO dbo;
|
||||
/*
|
||||
{
|
||||
"type": "record",
|
||||
"name": "gpu.vm",
|
||||
"namespace": "org.apache.nifi",
|
||||
"fields": [
|
||||
{"name":"objUUID", "type":{"type": "string", "logicalType": "uuid"}},
|
||||
{"name":"groupUUID", "type":[{"type": "string", "logicalType": "uuid"} ,"null"]},
|
||||
{"name":"objId", "type":["string" ,"null"]},
|
||||
{"name":"ClientID", "type":["int" ,"null"]},
|
||||
{"name":"VCD", "type":["string" ,"null"]},
|
||||
{"name":"Org", "type":["string" ,"null"]},
|
||||
{"name":"OrgVDC", "type":["string" ,"null"]},
|
||||
{"name":"vCenter", "type":["string" ,"null"]},
|
||||
{"name":"GPU", "type":["string" ,"null"]},
|
||||
{"name":"VCD", "type":["string" ,"null"]},
|
||||
{"name":"dt_load","type":{"type": "long", "logicalType": "local-timestamp-millis"}}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
DROP TABLE IF EXISTS gpu.vm_power_state;
|
||||
CREATE TABLE gpu.vm_power_state (
|
||||
objId varchar(255) NULL
|
||||
,ts timestamptz NOT NULL -- без таймштампа загрузки
|
||||
,value int NULL
|
||||
,CONSTRAINT PK_vm_power_state PRIMARY KEY(objId, ts)
|
||||
);
|
||||
ALTER TABLE gpu.vm_power_state OWNER TO dbo;
|
||||
/*
|
||||
{
|
||||
"type": "record",
|
||||
"name": "gpu.vm_power_state,
|
||||
"namespace": "org.apache.nifi",
|
||||
"fields": [
|
||||
{"name":"objId", "type":["string" ,"null"]},
|
||||
{"name":"ts","type":{"type": "long", "logicalType": "local-timestamp-millis"}},
|
||||
{"name":"value", "type":["int" ,"null"]}
|
||||
]
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,828 @@
|
||||
--
|
||||
-- PostgreSQL database dump
|
||||
--
|
||||
|
||||
-- Dumped from database version 16.0
|
||||
-- Dumped by pg_dump version 16.4
|
||||
|
||||
-- Started on 2025-09-15 09:50:58
|
||||
|
||||
SET statement_timeout = 0;
|
||||
SET lock_timeout = 0;
|
||||
SET idle_in_transaction_session_timeout = 0;
|
||||
SET client_encoding = 'UTF8';
|
||||
SET standard_conforming_strings = on;
|
||||
SELECT pg_catalog.set_config('search_path', '', false);
|
||||
SET check_function_bodies = false;
|
||||
SET xmloption = content;
|
||||
SET client_min_messages = warning;
|
||||
SET row_security = off;
|
||||
|
||||
SET default_tablespace = '';
|
||||
|
||||
SET default_table_access_method = heap;
|
||||
|
||||
--
|
||||
-- TOC entry 230 (class 1259 OID 2160668)
|
||||
-- Name: bucket_info; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE TABLE s3billing.bucket_info (
|
||||
id integer NOT NULL,
|
||||
bucket_id character varying(255) NOT NULL,
|
||||
name character varying(255) NOT NULL,
|
||||
marker character varying(255) NOT NULL,
|
||||
placement_id bigint DEFAULT 0 NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE s3billing.bucket_info OWNER TO s3billing;
|
||||
|
||||
--
|
||||
-- TOC entry 229 (class 1259 OID 2160667)
|
||||
-- Name: bucket_info_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE SEQUENCE s3billing.bucket_info_id_seq
|
||||
AS integer
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
ALTER SEQUENCE s3billing.bucket_info_id_seq OWNER TO s3billing;
|
||||
|
||||
--
|
||||
-- TOC entry 3448 (class 0 OID 0)
|
||||
-- Dependencies: 229
|
||||
-- Name: bucket_info_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER SEQUENCE s3billing.bucket_info_id_seq OWNED BY s3billing.bucket_info.id;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 226 (class 1259 OID 2160642)
|
||||
-- Name: bucket_stat; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE TABLE s3billing.bucket_stat (
|
||||
bucket_id bigint,
|
||||
num_shards bigint NOT NULL,
|
||||
tenant character varying(255) DEFAULT NULL::character varying,
|
||||
zone_group bigint NOT NULL,
|
||||
placement_id bigint NOT NULL,
|
||||
explicit_placement_data_pool character varying(255) DEFAULT NULL::character varying,
|
||||
explicit_placement_data_extra_pool character varying(255) DEFAULT NULL::character varying,
|
||||
explicit_placement_index_pool character varying(255) DEFAULT NULL::character varying,
|
||||
index_type_id bigint NOT NULL,
|
||||
versioned boolean DEFAULT false,
|
||||
versioning_enabled boolean DEFAULT false,
|
||||
object_lock_enabled boolean DEFAULT false,
|
||||
mfa_enabled boolean DEFAULT false,
|
||||
owner character varying(255) NOT NULL,
|
||||
bucket_quota_enabled boolean DEFAULT false,
|
||||
bucket_quota_check_on_raw boolean DEFAULT false,
|
||||
bucket_quota_max_size bigint NOT NULL,
|
||||
bucket_quota_max_size_kb bigint NOT NULL,
|
||||
bucket_quota_max_objects bigint NOT NULL,
|
||||
usage_rgw_main_size bigint NOT NULL,
|
||||
usage_rgw_main_size_actual bigint NOT NULL,
|
||||
usage_rgw_main_size_utilized bigint NOT NULL,
|
||||
usage_rgw_main_size_kb bigint NOT NULL,
|
||||
usage_rgw_main_size_kb_actual bigint NOT NULL,
|
||||
usage_rgw_main_size_kb_utilized bigint NOT NULL,
|
||||
usage_rgw_main_num_objects bigint NOT NULL,
|
||||
usage_rgw_multimeta_size bigint,
|
||||
usage_rgw_multimeta_size_actual bigint,
|
||||
usage_rgw_multimeta_size_utilized bigint,
|
||||
usage_rgw_multimeta_size_kb bigint,
|
||||
usage_rgw_multimeta_size_kb_actual bigint,
|
||||
usage_rgw_multimeta_size_kb_utilized bigint,
|
||||
usage_rgw_multimeta_num_objects bigint,
|
||||
creation_time timestamp without time zone NOT NULL,
|
||||
mtime timestamp without time zone NOT NULL,
|
||||
timestamp_addition timestamp without time zone DEFAULT date_trunc('hour'::text, CURRENT_TIMESTAMP)
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE s3billing.bucket_stat OWNER TO s3billing;
|
||||
|
||||
--
|
||||
-- TOC entry 245 (class 1259 OID 2160763)
|
||||
-- Name: category; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE TABLE s3billing.category (
|
||||
id integer NOT NULL,
|
||||
name character varying(255) NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE s3billing.category OWNER TO s3billing;
|
||||
|
||||
--
|
||||
-- TOC entry 244 (class 1259 OID 2160762)
|
||||
-- Name: category_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE SEQUENCE s3billing.category_id_seq
|
||||
AS integer
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
ALTER SEQUENCE s3billing.category_id_seq OWNER TO s3billing;
|
||||
|
||||
--
|
||||
-- TOC entry 3451 (class 0 OID 0)
|
||||
-- Dependencies: 244
|
||||
-- Name: category_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER SEQUENCE s3billing.category_id_seq OWNED BY s3billing.category.id;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 225 (class 1259 OID 2160635)
|
||||
-- Name: goose_db_version; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE TABLE s3billing.goose_db_version (
|
||||
id integer NOT NULL,
|
||||
version_id bigint NOT NULL,
|
||||
is_applied boolean NOT NULL,
|
||||
tstamp timestamp without time zone DEFAULT now() NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE s3billing.goose_db_version OWNER TO s3billing;
|
||||
|
||||
--
|
||||
-- TOC entry 224 (class 1259 OID 2160634)
|
||||
-- Name: goose_db_version_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE s3billing.goose_db_version ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY (
|
||||
SEQUENCE NAME s3billing.goose_db_version_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 234 (class 1259 OID 2160684)
|
||||
-- Name: index_type; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE TABLE s3billing.index_type (
|
||||
id integer NOT NULL,
|
||||
name character varying(255) NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE s3billing.index_type OWNER TO s3billing;
|
||||
|
||||
--
|
||||
-- TOC entry 233 (class 1259 OID 2160683)
|
||||
-- Name: index_type_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE SEQUENCE s3billing.index_type_id_seq
|
||||
AS integer
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
ALTER SEQUENCE s3billing.index_type_id_seq OWNER TO s3billing;
|
||||
|
||||
--
|
||||
-- TOC entry 3454 (class 0 OID 0)
|
||||
-- Dependencies: 233
|
||||
-- Name: index_type_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER SEQUENCE s3billing.index_type_id_seq OWNED BY s3billing.index_type.id;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 232 (class 1259 OID 2160677)
|
||||
-- Name: placement; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE TABLE s3billing.placement (
|
||||
id integer NOT NULL,
|
||||
name character varying(255) NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE s3billing.placement OWNER TO s3billing;
|
||||
|
||||
--
|
||||
-- TOC entry 231 (class 1259 OID 2160676)
|
||||
-- Name: placement_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE SEQUENCE s3billing.placement_id_seq
|
||||
AS integer
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
ALTER SEQUENCE s3billing.placement_id_seq OWNER TO s3billing;
|
||||
|
||||
--
|
||||
-- TOC entry 3456 (class 0 OID 0)
|
||||
-- Dependencies: 231
|
||||
-- Name: placement_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER SEQUENCE s3billing.placement_id_seq OWNED BY s3billing.placement.id;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 239 (class 1259 OID 2160705)
|
||||
-- Name: usage_bucket_by_user; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE TABLE s3billing.usage_bucket_by_user (
|
||||
bucketid bigint,
|
||||
"time" timestamp without time zone NOT NULL,
|
||||
bytes_sent bigint NOT NULL,
|
||||
bytes_received bigint NOT NULL,
|
||||
ops bigint NOT NULL,
|
||||
successful_ops bigint NOT NULL,
|
||||
date_start timestamp without time zone NOT NULL,
|
||||
date_end timestamp without time zone NOT NULL,
|
||||
user_id bigint NOT NULL,
|
||||
category_id bigint NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE s3billing.usage_bucket_by_user OWNER TO s3billing;
|
||||
|
||||
--
|
||||
-- TOC entry 238 (class 1259 OID 2160698)
|
||||
-- Name: usage_stat_summary; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE TABLE s3billing.usage_stat_summary (
|
||||
id integer NOT NULL,
|
||||
userid character varying(255) NOT NULL,
|
||||
category character varying(255) NOT NULL,
|
||||
bytes_sent bigint NOT NULL,
|
||||
bytes_received bigint NOT NULL,
|
||||
ops bigint NOT NULL,
|
||||
successful_ops bigint NOT NULL,
|
||||
date_start timestamp without time zone NOT NULL,
|
||||
date_end timestamp without time zone NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE s3billing.usage_stat_summary OWNER TO s3billing;
|
||||
|
||||
--
|
||||
-- TOC entry 237 (class 1259 OID 2160697)
|
||||
-- Name: usage_stat_summary_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE SEQUENCE s3billing.usage_stat_summary_id_seq
|
||||
AS integer
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
ALTER SEQUENCE s3billing.usage_stat_summary_id_seq OWNER TO s3billing;
|
||||
|
||||
--
|
||||
-- TOC entry 3459 (class 0 OID 0)
|
||||
-- Dependencies: 237
|
||||
-- Name: usage_stat_summary_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER SEQUENCE s3billing.usage_stat_summary_id_seq OWNED BY s3billing.usage_stat_summary.id;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 236 (class 1259 OID 2160691)
|
||||
-- Name: usage_stat_total; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE TABLE s3billing.usage_stat_total (
|
||||
id integer NOT NULL,
|
||||
userid character varying(255) NOT NULL,
|
||||
bytes_sent bigint NOT NULL,
|
||||
bytes_received bigint NOT NULL,
|
||||
ops bigint NOT NULL,
|
||||
successful_ops bigint NOT NULL,
|
||||
date_start timestamp without time zone NOT NULL,
|
||||
date_end timestamp without time zone NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE s3billing.usage_stat_total OWNER TO s3billing;
|
||||
|
||||
--
|
||||
-- TOC entry 235 (class 1259 OID 2160690)
|
||||
-- Name: usage_stat_total_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE SEQUENCE s3billing.usage_stat_total_id_seq
|
||||
AS integer
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
ALTER SEQUENCE s3billing.usage_stat_total_id_seq OWNER TO s3billing;
|
||||
|
||||
--
|
||||
-- TOC entry 3461 (class 0 OID 0)
|
||||
-- Dependencies: 235
|
||||
-- Name: usage_stat_total_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER SEQUENCE s3billing.usage_stat_total_id_seq OWNED BY s3billing.usage_stat_total.id;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 243 (class 1259 OID 2160751)
|
||||
-- Name: user_info; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE TABLE s3billing.user_info (
|
||||
id integer NOT NULL,
|
||||
name character varying(255) NOT NULL,
|
||||
owner character varying(255) NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE s3billing.user_info OWNER TO s3billing;
|
||||
|
||||
--
|
||||
-- TOC entry 242 (class 1259 OID 2160750)
|
||||
-- Name: user_info_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE SEQUENCE s3billing.user_info_id_seq
|
||||
AS integer
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
ALTER SEQUENCE s3billing.user_info_id_seq OWNER TO s3billing;
|
||||
|
||||
--
|
||||
-- TOC entry 3463 (class 0 OID 0)
|
||||
-- Dependencies: 242
|
||||
-- Name: user_info_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER SEQUENCE s3billing.user_info_id_seq OWNED BY s3billing.user_info.id;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 241 (class 1259 OID 2160712)
|
||||
-- Name: user_quota_bucket; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE TABLE s3billing.user_quota_bucket (
|
||||
id integer NOT NULL,
|
||||
userid character varying(255) NOT NULL,
|
||||
enabled boolean DEFAULT false,
|
||||
check_on_raw boolean DEFAULT false,
|
||||
max_size bigint NOT NULL,
|
||||
max_size_kb bigint NOT NULL,
|
||||
max_objects bigint NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE s3billing.user_quota_bucket OWNER TO s3billing;
|
||||
|
||||
--
|
||||
-- TOC entry 240 (class 1259 OID 2160711)
|
||||
-- Name: user_quota_bucket_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE SEQUENCE s3billing.user_quota_bucket_id_seq
|
||||
AS integer
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
ALTER SEQUENCE s3billing.user_quota_bucket_id_seq OWNER TO s3billing;
|
||||
|
||||
--
|
||||
-- TOC entry 3465 (class 0 OID 0)
|
||||
-- Dependencies: 240
|
||||
-- Name: user_quota_bucket_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER SEQUENCE s3billing.user_quota_bucket_id_seq OWNED BY s3billing.user_quota_bucket.id;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 228 (class 1259 OID 2160661)
|
||||
-- Name: zone_group; Type: TABLE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE TABLE s3billing.zone_group (
|
||||
id integer NOT NULL,
|
||||
name uuid NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE s3billing.zone_group OWNER TO s3billing;
|
||||
|
||||
--
|
||||
-- TOC entry 227 (class 1259 OID 2160660)
|
||||
-- Name: zone_group_id_seq; Type: SEQUENCE; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE SEQUENCE s3billing.zone_group_id_seq
|
||||
AS integer
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
ALTER SEQUENCE s3billing.zone_group_id_seq OWNER TO s3billing;
|
||||
|
||||
--
|
||||
-- TOC entry 3467 (class 0 OID 0)
|
||||
-- Dependencies: 227
|
||||
-- Name: zone_group_id_seq; Type: SEQUENCE OWNED BY; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER SEQUENCE s3billing.zone_group_id_seq OWNED BY s3billing.zone_group.id;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3258 (class 2604 OID 2160671)
|
||||
-- Name: bucket_info id; Type: DEFAULT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.bucket_info ALTER COLUMN id SET DEFAULT nextval('s3billing.bucket_info_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3268 (class 2604 OID 2160766)
|
||||
-- Name: category id; Type: DEFAULT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.category ALTER COLUMN id SET DEFAULT nextval('s3billing.category_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3261 (class 2604 OID 2160687)
|
||||
-- Name: index_type id; Type: DEFAULT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.index_type ALTER COLUMN id SET DEFAULT nextval('s3billing.index_type_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3260 (class 2604 OID 2160680)
|
||||
-- Name: placement id; Type: DEFAULT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.placement ALTER COLUMN id SET DEFAULT nextval('s3billing.placement_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3263 (class 2604 OID 2160701)
|
||||
-- Name: usage_stat_summary id; Type: DEFAULT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.usage_stat_summary ALTER COLUMN id SET DEFAULT nextval('s3billing.usage_stat_summary_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3262 (class 2604 OID 2160694)
|
||||
-- Name: usage_stat_total id; Type: DEFAULT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.usage_stat_total ALTER COLUMN id SET DEFAULT nextval('s3billing.usage_stat_total_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3267 (class 2604 OID 2160754)
|
||||
-- Name: user_info id; Type: DEFAULT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.user_info ALTER COLUMN id SET DEFAULT nextval('s3billing.user_info_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3264 (class 2604 OID 2160715)
|
||||
-- Name: user_quota_bucket id; Type: DEFAULT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.user_quota_bucket ALTER COLUMN id SET DEFAULT nextval('s3billing.user_quota_bucket_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3257 (class 2604 OID 2160664)
|
||||
-- Name: zone_group id; Type: DEFAULT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.zone_group ALTER COLUMN id SET DEFAULT nextval('s3billing.zone_group_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3278 (class 2606 OID 2160675)
|
||||
-- Name: bucket_info bucket_info_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.bucket_info
|
||||
ADD CONSTRAINT bucket_info_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3273 (class 2606 OID 2476484)
|
||||
-- Name: bucket_stat bucket_stat_unique; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.bucket_stat
|
||||
ADD CONSTRAINT bucket_stat_unique UNIQUE (bucket_id, placement_id, timestamp_addition);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3298 (class 2606 OID 2160768)
|
||||
-- Name: category category_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.category
|
||||
ADD CONSTRAINT category_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3270 (class 2606 OID 2160640)
|
||||
-- Name: goose_db_version goose_db_version_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.goose_db_version
|
||||
ADD CONSTRAINT goose_db_version_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3284 (class 2606 OID 2160689)
|
||||
-- Name: index_type index_type_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.index_type
|
||||
ADD CONSTRAINT index_type_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3282 (class 2606 OID 2160682)
|
||||
-- Name: placement placement_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.placement
|
||||
ADD CONSTRAINT placement_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3290 (class 2606 OID 2476705)
|
||||
-- Name: usage_bucket_by_user usage_bucket_by_user_unique; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.usage_bucket_by_user
|
||||
ADD CONSTRAINT usage_bucket_by_user_unique UNIQUE (bucketid, date_start, date_end, user_id, category_id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3288 (class 2606 OID 2160703)
|
||||
-- Name: usage_stat_summary usage_stat_summary_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.usage_stat_summary
|
||||
ADD CONSTRAINT usage_stat_summary_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3286 (class 2606 OID 2160696)
|
||||
-- Name: usage_stat_total usage_stat_total_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.usage_stat_total
|
||||
ADD CONSTRAINT usage_stat_total_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3295 (class 2606 OID 2160758)
|
||||
-- Name: user_info user_info_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.user_info
|
||||
ADD CONSTRAINT user_info_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3292 (class 2606 OID 2160719)
|
||||
-- Name: user_quota_bucket user_quota_bucket_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.user_quota_bucket
|
||||
ADD CONSTRAINT user_quota_bucket_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3275 (class 2606 OID 2160666)
|
||||
-- Name: zone_group zone_group_pkey; Type: CONSTRAINT; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY s3billing.zone_group
|
||||
ADD CONSTRAINT zone_group_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3276 (class 1259 OID 2474077)
|
||||
-- Name: bucket_info_name_idx; Type: INDEX; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE INDEX bucket_info_name_idx ON s3billing.bucket_info USING btree (name);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3279 (class 1259 OID 2474078)
|
||||
-- Name: bucket_info_placement_id_idx; Type: INDEX; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE INDEX bucket_info_placement_id_idx ON s3billing.bucket_info USING btree (placement_id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3271 (class 1259 OID 2474094)
|
||||
-- Name: bucket_stat_owner_idx; Type: INDEX; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE INDEX bucket_stat_owner_idx ON s3billing.bucket_stat USING btree (owner);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3296 (class 1259 OID 2474445)
|
||||
-- Name: category_name_idx; Type: INDEX; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX category_name_idx ON s3billing.category USING btree (name);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3280 (class 1259 OID 2474468)
|
||||
-- Name: placement_name_idx; Type: INDEX; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX placement_name_idx ON s3billing.placement USING btree (name);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3293 (class 1259 OID 2474438)
|
||||
-- Name: user_info_name_idx; Type: INDEX; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
CREATE INDEX user_info_name_idx ON s3billing.user_info USING btree (name);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3447 (class 0 OID 0)
|
||||
-- Dependencies: 230
|
||||
-- Name: TABLE bucket_info; Type: ACL; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
GRANT SELECT ON TABLE s3billing.bucket_info TO grafanabilling;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3449 (class 0 OID 0)
|
||||
-- Dependencies: 226
|
||||
-- Name: TABLE bucket_stat; Type: ACL; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
GRANT SELECT ON TABLE s3billing.bucket_stat TO grafanabilling;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3450 (class 0 OID 0)
|
||||
-- Dependencies: 245
|
||||
-- Name: TABLE category; Type: ACL; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
GRANT SELECT ON TABLE s3billing.category TO grafanabilling;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3452 (class 0 OID 0)
|
||||
-- Dependencies: 225
|
||||
-- Name: TABLE goose_db_version; Type: ACL; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
GRANT SELECT ON TABLE s3billing.goose_db_version TO grafanabilling;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3453 (class 0 OID 0)
|
||||
-- Dependencies: 234
|
||||
-- Name: TABLE index_type; Type: ACL; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
GRANT SELECT ON TABLE s3billing.index_type TO grafanabilling;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3455 (class 0 OID 0)
|
||||
-- Dependencies: 232
|
||||
-- Name: TABLE placement; Type: ACL; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
GRANT SELECT ON TABLE s3billing.placement TO grafanabilling;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3457 (class 0 OID 0)
|
||||
-- Dependencies: 239
|
||||
-- Name: TABLE usage_bucket_by_user; Type: ACL; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
GRANT SELECT ON TABLE s3billing.usage_bucket_by_user TO grafanabilling;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3458 (class 0 OID 0)
|
||||
-- Dependencies: 238
|
||||
-- Name: TABLE usage_stat_summary; Type: ACL; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
GRANT SELECT ON TABLE s3billing.usage_stat_summary TO grafanabilling;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3460 (class 0 OID 0)
|
||||
-- Dependencies: 236
|
||||
-- Name: TABLE usage_stat_total; Type: ACL; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
GRANT SELECT ON TABLE s3billing.usage_stat_total TO grafanabilling;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3462 (class 0 OID 0)
|
||||
-- Dependencies: 243
|
||||
-- Name: TABLE user_info; Type: ACL; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
GRANT SELECT ON TABLE s3billing.user_info TO grafanabilling;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3464 (class 0 OID 0)
|
||||
-- Dependencies: 241
|
||||
-- Name: TABLE user_quota_bucket; Type: ACL; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
GRANT SELECT ON TABLE s3billing.user_quota_bucket TO grafanabilling;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3466 (class 0 OID 0)
|
||||
-- Dependencies: 228
|
||||
-- Name: TABLE zone_group; Type: ACL; Schema: s3billing; Owner: s3billing
|
||||
--
|
||||
|
||||
GRANT SELECT ON TABLE s3billing.zone_group TO grafanabilling;
|
||||
|
||||
|
||||
-- Completed on 2025-09-15 09:50:59
|
||||
|
||||
--
|
||||
-- PostgreSQL database dump complete
|
||||
--
|
||||
|
||||
@@ -0,0 +1,278 @@
|
||||
--
|
||||
-- PostgreSQL database dump
|
||||
--
|
||||
|
||||
-- Dumped from database version 16.0
|
||||
-- Dumped by pg_dump version 16.4
|
||||
|
||||
-- Started on 2025-09-15 09:53:16
|
||||
|
||||
SET statement_timeout = 0;
|
||||
SET lock_timeout = 0;
|
||||
SET idle_in_transaction_session_timeout = 0;
|
||||
SET client_encoding = 'UTF8';
|
||||
SET standard_conforming_strings = on;
|
||||
SELECT pg_catalog.set_config('search_path', '', false);
|
||||
SET check_function_bodies = false;
|
||||
SET xmloption = content;
|
||||
SET client_min_messages = warning;
|
||||
SET row_security = off;
|
||||
|
||||
SET default_tablespace = '';
|
||||
|
||||
SET default_table_access_method = heap;
|
||||
|
||||
--
|
||||
-- TOC entry 222 (class 1259 OID 1893983)
|
||||
-- Name: capacity_resource; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
CREATE TABLE ngcloud_ru.capacity_resource (
|
||||
vdc_id uuid NOT NULL,
|
||||
"timestamp" timestamp with time zone NOT NULL,
|
||||
cpu_allocated integer NOT NULL,
|
||||
cpu_limit integer NOT NULL,
|
||||
cpu_reserved integer NOT NULL,
|
||||
cpu_used integer NOT NULL,
|
||||
cpu_speed integer NOT NULL,
|
||||
mem_allocated integer NOT NULL,
|
||||
mem_limit integer NOT NULL,
|
||||
mem_reserved integer NOT NULL,
|
||||
mem_used integer NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE ngcloud_ru.capacity_resource OWNER TO vc_billing;
|
||||
|
||||
--
|
||||
-- TOC entry 223 (class 1259 OID 1893993)
|
||||
-- Name: capacity_storage; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
CREATE TABLE ngcloud_ru.capacity_storage (
|
||||
vdc_id uuid NOT NULL,
|
||||
storage_profile_types_id integer NOT NULL,
|
||||
"timestamp" timestamp with time zone NOT NULL,
|
||||
id uuid NOT NULL,
|
||||
"limit" integer NOT NULL,
|
||||
used integer NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE ngcloud_ru.capacity_storage OWNER TO vc_billing;
|
||||
|
||||
--
|
||||
-- TOC entry 220 (class 1259 OID 1893965)
|
||||
-- Name: storage_profile_types; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
CREATE TABLE ngcloud_ru.storage_profile_types (
|
||||
id integer NOT NULL,
|
||||
name character varying(255) NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE ngcloud_ru.storage_profile_types OWNER TO vc_billing;
|
||||
|
||||
--
|
||||
-- TOC entry 219 (class 1259 OID 1893964)
|
||||
-- Name: storage_profile_types_id_seq; Type: SEQUENCE; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
CREATE SEQUENCE ngcloud_ru.storage_profile_types_id_seq
|
||||
AS integer
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
ALTER SEQUENCE ngcloud_ru.storage_profile_types_id_seq OWNER TO vc_billing;
|
||||
|
||||
--
|
||||
-- TOC entry 3413 (class 0 OID 0)
|
||||
-- Dependencies: 219
|
||||
-- Name: storage_profile_types_id_seq; Type: SEQUENCE OWNED BY; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
ALTER SEQUENCE ngcloud_ru.storage_profile_types_id_seq OWNED BY ngcloud_ru.storage_profile_types.id;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 218 (class 1259 OID 1893959)
|
||||
-- Name: tenant; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
CREATE TABLE ngcloud_ru.tenant (
|
||||
id uuid NOT NULL,
|
||||
name character varying(255) NOT NULL,
|
||||
wzcode bigint
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE ngcloud_ru.tenant OWNER TO vc_billing;
|
||||
|
||||
--
|
||||
-- TOC entry 221 (class 1259 OID 1893973)
|
||||
-- Name: vdc; Type: TABLE; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
CREATE TABLE ngcloud_ru.vdc (
|
||||
id uuid NOT NULL,
|
||||
tenant_id uuid NOT NULL,
|
||||
name character varying(255) NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE ngcloud_ru.vdc OWNER TO vc_billing;
|
||||
|
||||
--
|
||||
-- TOC entry 3245 (class 2604 OID 1893968)
|
||||
-- Name: storage_profile_types id; Type: DEFAULT; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY ngcloud_ru.storage_profile_types ALTER COLUMN id SET DEFAULT nextval('ngcloud_ru.storage_profile_types_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3255 (class 2606 OID 1893987)
|
||||
-- Name: capacity_resource capacity_resource_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY ngcloud_ru.capacity_resource
|
||||
ADD CONSTRAINT capacity_resource_pkey PRIMARY KEY (vdc_id, "timestamp");
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3257 (class 2606 OID 1893997)
|
||||
-- Name: capacity_storage capacity_storage_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY ngcloud_ru.capacity_storage
|
||||
ADD CONSTRAINT capacity_storage_pkey PRIMARY KEY (vdc_id, id, "timestamp");
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3249 (class 2606 OID 1893972)
|
||||
-- Name: storage_profile_types storage_profile_types_name_key; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY ngcloud_ru.storage_profile_types
|
||||
ADD CONSTRAINT storage_profile_types_name_key UNIQUE (name);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3251 (class 2606 OID 1893970)
|
||||
-- Name: storage_profile_types storage_profile_types_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY ngcloud_ru.storage_profile_types
|
||||
ADD CONSTRAINT storage_profile_types_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3247 (class 2606 OID 1893963)
|
||||
-- Name: tenant tenant_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY ngcloud_ru.tenant
|
||||
ADD CONSTRAINT tenant_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3253 (class 2606 OID 1893977)
|
||||
-- Name: vdc vdc_pkey; Type: CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY ngcloud_ru.vdc
|
||||
ADD CONSTRAINT vdc_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3259 (class 2606 OID 1893988)
|
||||
-- Name: capacity_resource capacity_resource_vdc_id_fkey; Type: FK CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY ngcloud_ru.capacity_resource
|
||||
ADD CONSTRAINT capacity_resource_vdc_id_fkey FOREIGN KEY (vdc_id) REFERENCES ngcloud_ru.vdc(id) ON DELETE CASCADE;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3260 (class 2606 OID 1894003)
|
||||
-- Name: capacity_storage capacity_storage_storage_profile_types_id_fkey; Type: FK CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY ngcloud_ru.capacity_storage
|
||||
ADD CONSTRAINT capacity_storage_storage_profile_types_id_fkey FOREIGN KEY (storage_profile_types_id) REFERENCES ngcloud_ru.storage_profile_types(id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3261 (class 2606 OID 1893998)
|
||||
-- Name: capacity_storage capacity_storage_vdc_id_fkey; Type: FK CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY ngcloud_ru.capacity_storage
|
||||
ADD CONSTRAINT capacity_storage_vdc_id_fkey FOREIGN KEY (vdc_id) REFERENCES ngcloud_ru.vdc(id) ON DELETE CASCADE;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3258 (class 2606 OID 1893978)
|
||||
-- Name: vdc vdc_tenant_id_fkey; Type: FK CONSTRAINT; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY ngcloud_ru.vdc
|
||||
ADD CONSTRAINT vdc_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES ngcloud_ru.tenant(id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3410 (class 0 OID 0)
|
||||
-- Dependencies: 222
|
||||
-- Name: TABLE capacity_resource; Type: ACL; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
GRANT SELECT ON TABLE ngcloud_ru.capacity_resource TO grafanabilling;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3411 (class 0 OID 0)
|
||||
-- Dependencies: 223
|
||||
-- Name: TABLE capacity_storage; Type: ACL; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
GRANT SELECT ON TABLE ngcloud_ru.capacity_storage TO grafanabilling;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3412 (class 0 OID 0)
|
||||
-- Dependencies: 220
|
||||
-- Name: TABLE storage_profile_types; Type: ACL; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
GRANT SELECT ON TABLE ngcloud_ru.storage_profile_types TO grafanabilling;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3414 (class 0 OID 0)
|
||||
-- Dependencies: 218
|
||||
-- Name: TABLE tenant; Type: ACL; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
GRANT SELECT ON TABLE ngcloud_ru.tenant TO grafanabilling;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 3415 (class 0 OID 0)
|
||||
-- Dependencies: 221
|
||||
-- Name: TABLE vdc; Type: ACL; Schema: ngcloud_ru; Owner: vc_billing
|
||||
--
|
||||
|
||||
GRANT SELECT ON TABLE ngcloud_ru.vdc TO grafanabilling;
|
||||
|
||||
|
||||
-- Completed on 2025-09-15 09:53:18
|
||||
|
||||
--
|
||||
-- PostgreSQL database dump complete
|
||||
--
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
CREATE SCHEMA IF NOT EXISTS vmreports;
|
||||
|
||||
ALTER SCHEMA vmreports OWNER TO dbo;
|
||||
GRANT USAGE ON SCHEMA vmreports TO nifi;
|
||||
|
||||
GRANT ALL ON ALL TABLES IN SCHEMA vmreports TO nifi;
|
||||
GRANT ALL ON ALL SEQUENCES IN SCHEMA vmreports TO nifi;
|
||||
|
||||
--ALTER DEFAULT PRIVILEGES IN SCHEMA vmreports GRANT ALL ON TABLES TO nifi;
|
||||
--ALTER DEFAULT PRIVILEGES IN SCHEMA vmreports GRANT ALL ON SEQUENCES TO nifi;
|
||||
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo, postgres IN SCHEMA vmreports GRANT ALL ON TABLES TO nifi;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo, postgres IN SCHEMA vmreports GRANT SELECT ON TABLES TO appserver;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo, postgres IN SCHEMA vmreports GRANT ALL ON SEQUENCES TO nifi;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo, postgres IN SCHEMA vmreports GRANT USAGE ON SEQUENCES TO appserver;
|
||||
|
||||
drop table if exists vmreports.host;
|
||||
create table vmreports.host(
|
||||
"Name" varchar(255) NULL,
|
||||
"Model" varchar(255) NULL,
|
||||
"Cluster" varchar(255) NULL,
|
||||
"Cluster_v2" varchar(255) NULL,
|
||||
"Maintenance" varchar(255) NULL,
|
||||
|
||||
"CPU_Cores" float NULL, -- per host, not per socket
|
||||
"CPU_Sockets" float NULL, -- not used in caclulations
|
||||
"CPU_Speed" float NULL,
|
||||
"RAM_Total" float NULL,
|
||||
"RAM_Used" float NULL,
|
||||
"CPU_Used" float NULL,
|
||||
"CPU_Used_AVG" float NULL,
|
||||
"CPU_Contention_95" float NULL,
|
||||
"HT_Active" boolean NULL,
|
||||
"CPUtoVM" float NULL,
|
||||
"RAMtoVM" float NULL,
|
||||
"Object_UUID" uuid NOT NULL,
|
||||
ts timestamptz NOT NULL
|
||||
,CONSTRAINT PK_host PRIMARY KEY (ts, "Object_UUID")
|
||||
);
|
||||
--grant all on vmreports.host to nifi;
|
||||
|
||||
drop table if exists vmreports.compute;
|
||||
create table vmreports.compute (
|
||||
|
||||
"Name" varchar(255) NULL,
|
||||
"UUID_VM" varchar(255) NULL,
|
||||
"VDC" varchar(255) NULL,
|
||||
"Organization_UUID" uuid NULL,
|
||||
"Organization" varchar(255) NULL,
|
||||
"WZ" varchar(255) NULL,
|
||||
"Cluster" varchar(255) NULL,
|
||||
"Host" varchar(255) NULL,
|
||||
"Host_Model" varchar(255) NULL,
|
||||
"CPU_Model" varchar(255) NULL,
|
||||
|
||||
"Host_CPU_Cores" float NULL,
|
||||
"Host_CPU_Sockets" float NULL,
|
||||
"Host_CPU_Speed" float NULL,
|
||||
"Host_RAM" float NULL,
|
||||
"Host_CPU_Used" float NULL,
|
||||
"Host_CPU_Used_Avg" float NULL,
|
||||
"VDC_CPU_Reserv" float NULL,
|
||||
"VDC_CPU_Speed" float NULL,
|
||||
"VM_vCPU_count" float NULL,
|
||||
"VM_CPU_Used" float NULL,
|
||||
"VM_CPU_Used_AVG" float NULL,
|
||||
"VM_CPU_Reserv_GHz" float NULL,
|
||||
"VM_CPU_Reserv_perc" float NULL,
|
||||
"VM_RAM_Allocated" float NULL,
|
||||
"VM_RAM_Used" float NULL,
|
||||
"VM_is_ON" float NULL,
|
||||
--"Summary": false,
|
||||
--"Grand Total": false,
|
||||
--"Group UUID": null,
|
||||
"Object_UUID" uuid NOT NULL,
|
||||
ts timestamptz NOT NULL
|
||||
,CONSTRAINT PK_compute PRIMARY KEY (ts, "Object_UUID")
|
||||
);
|
||||
--grant all on vmreports.compute to nifi;
|
||||
|
||||
drop table if exists vmreports.storage;
|
||||
create table vmreports.storage (
|
||||
|
||||
"Name" varchar(255) NULL,
|
||||
"VM_UUID" varchar(255) NULL,
|
||||
"VDC" varchar(255) NULL,
|
||||
"Organization_UUID" uuid NULL,
|
||||
"Organization" varchar(255) NULL,
|
||||
"WZ" varchar(255) NULL,
|
||||
"Cluster" varchar(255) NULL,
|
||||
"Disk" varchar(255) NULL,
|
||||
"Storage_Policy" varchar(255) NULL,
|
||||
|
||||
"Disk_Allocated" float NULL,
|
||||
"Disk_Used" float NULL,
|
||||
"VM_is_ON" float NULL,
|
||||
"Object_UUID" uuid NOT NULL,
|
||||
ts timestamptz NOT NULL
|
||||
,CONSTRAINT PK_storage PRIMARY KEY (ts, "Object_UUID")
|
||||
);
|
||||
--grant all on vmreports.storage to nifi;
|
||||
|
||||
drop table if exists vmreports.vm_gpu;
|
||||
create table vmreports.vm_gpu (
|
||||
"Name" varchar(255) NULL,
|
||||
"ClientID" varchar(255) NULL, --WZ
|
||||
"VCD" varchar(255) NULL, --vcloud
|
||||
"Org" varchar(255) NULL,
|
||||
"OrgVDC" varchar(255) NULL,
|
||||
"vCenter" varchar(255) NULL,
|
||||
"GPU" jsonb NULL,
|
||||
"OrgStatus" varchar(255) NULL,
|
||||
"Object_UUID" uuid NOT NULL,
|
||||
ts timestamptz NOT NULL
|
||||
,CONSTRAINT PK_vm_gpu PRIMARY KEY (ts, "Object_UUID")
|
||||
);
|
||||
--grant all on vmreports.vm_gpu to nifi;
|
||||
|
||||
DROP TABLE IF EXISTS vmreports.vm_power_state;
|
||||
CREATE TABLE IF NOT EXISTS vmreports.vm_power_state
|
||||
(
|
||||
"Object_UUID" uuid NOT NULL,
|
||||
ts timestamp with time zone NOT NULL,
|
||||
value float,
|
||||
CONSTRAINT PK_vm_power_state PRIMARY KEY ("Object_UUID", ts)
|
||||
);
|
||||
--grant all on vmreports.vm_power_state to nifi;
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
--
|
||||
-- PostgreSQL database dump
|
||||
--
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 10 (class 2615 OID 9816969)
|
||||
-- Name: vmreports; Type: SCHEMA; Schema: -; Owner: dbo
|
||||
--
|
||||
|
||||
CREATE SCHEMA IF NOT EXISTS vmreports;
|
||||
ALTER SCHEMA vmreports OWNER TO dbo;
|
||||
GRANT USAGE ON SCHEMA vmreports TO nifi,appserver;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT SELECT ON TABLES TO appserver;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT ALL ON TABLES TO nifi;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT USAGE ON SEQUENCES TO nifi, appserver;
|
||||
|
||||
SET default_tablespace = '';
|
||||
|
||||
SET default_table_access_method = heap;
|
||||
|
||||
--
|
||||
-- TOC entry 721 (class 1259 OID 9816992)
|
||||
-- Name: compute; Type: TABLE; Schema: vmreports; Owner: smishchuk
|
||||
--
|
||||
|
||||
CREATE TABLE vmreports.compute (
|
||||
"Name" character varying(255),
|
||||
"UUID_VM" character varying(255),
|
||||
"VDC" character varying(255),
|
||||
"Organization_UUID" uuid,
|
||||
"Organization" character varying(255),
|
||||
"WZ" character varying(255),
|
||||
"Cluster" character varying(255),
|
||||
"Host" character varying(255),
|
||||
"Host_Model" character varying(255),
|
||||
"CPU_Model" character varying(255),
|
||||
"Host_CPU_Cores" double precision,
|
||||
"Host_CPU_Sockets" double precision,
|
||||
"Host_CPU_Speed" double precision,
|
||||
"Host_RAM" double precision,
|
||||
"Host_CPU_Used" double precision,
|
||||
"Host_CPU_Used_Avg" double precision,
|
||||
"VDC_CPU_Reserv" double precision,
|
||||
"VDC_CPU_Speed" double precision,
|
||||
"VM_vCPU_count" double precision,
|
||||
"VM_CPU_Used" double precision,
|
||||
"VM_CPU_Used_AVG" double precision,
|
||||
"VM_CPU_Reserv_GHz" double precision,
|
||||
"VM_CPU_Reserv_perc" double precision,
|
||||
"VM_RAM_Allocated" double precision,
|
||||
"VM_RAM_Used" double precision,
|
||||
"VM_is_ON" double precision,
|
||||
"Object_UUID" uuid NOT NULL,
|
||||
ts timestamp with time zone NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE vmreports.compute OWNER TO dbo;
|
||||
|
||||
--
|
||||
-- TOC entry 722 (class 1259 OID 9817004)
|
||||
-- Name: storage; Type: TABLE; Schema: vmreports; Owner: smishchuk
|
||||
--
|
||||
|
||||
CREATE TABLE vmreports.storage (
|
||||
"Name" character varying(255),
|
||||
"VM_UUID" character varying(255),
|
||||
"VDC" character varying(255),
|
||||
"Organization_UUID" uuid,
|
||||
"Organization" character varying(255),
|
||||
"WZ" character varying(255),
|
||||
"Cluster" character varying(255),
|
||||
"Disk" character varying(255),
|
||||
"Storage_Policy" character varying(255),
|
||||
"Disk_Allocated" double precision,
|
||||
"Disk_Used" double precision,
|
||||
"VM_is_ON" double precision,
|
||||
"Object_UUID" uuid NOT NULL,
|
||||
ts timestamp with time zone NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE vmreports.storage OWNER TO dbo;
|
||||
|
||||
--
|
||||
-- TOC entry 720 (class 1259 OID 9816984)
|
||||
-- Name: host; Type: TABLE; Schema: vmreports; Owner: smishchuk
|
||||
--
|
||||
|
||||
CREATE TABLE vmreports.host (
|
||||
"Name" character varying(255),
|
||||
"Model" character varying(255),
|
||||
"Cluster" character varying(255),
|
||||
"Maintenance" character varying(255),
|
||||
"CPU_Cores" double precision,
|
||||
"CPU_Sockets" double precision,
|
||||
"CPU_Speed" double precision,
|
||||
"RAM_Total" double precision,
|
||||
"RAM_Used" double precision,
|
||||
"CPU_Used" double precision,
|
||||
"CPU_Used_AVG" double precision,
|
||||
"CPU_Contention_95" double precision,
|
||||
"Object_UUID" uuid NOT NULL,
|
||||
ts timestamp with time zone NOT NULL,
|
||||
"Cluster_v2" character varying(255),
|
||||
"HT_Active" boolean,
|
||||
"CPUtoVM" double precision,
|
||||
"RAMtoVM" double precision
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE vmreports.host OWNER TO dbo;
|
||||
|
||||
--
|
||||
-- TOC entry 733 (class 1259 OID 11093092)
|
||||
-- Name: vm_gpu; Type: TABLE; Schema: vmreports; Owner: smishchuk
|
||||
--
|
||||
|
||||
CREATE TABLE vmreports.vm_gpu (
|
||||
"Name" character varying(255),
|
||||
"ClientID" character varying(255),
|
||||
"VCD" character varying(255),
|
||||
"Org" character varying(255),
|
||||
"OrgVDC" character varying(255),
|
||||
"vCenter" character varying(255),
|
||||
"GPU" jsonb,
|
||||
"OrgStatus" character varying(255),
|
||||
"Object_UUID" uuid NOT NULL,
|
||||
ts timestamp with time zone NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE vmreports.vm_gpu OWNER TO dbo;
|
||||
|
||||
--
|
||||
-- TOC entry 732 (class 1259 OID 11093087)
|
||||
-- Name: vm_power_state; Type: TABLE; Schema: vmreports; Owner: smishchuk
|
||||
--
|
||||
|
||||
CREATE TABLE vmreports.vm_power_state (
|
||||
"Object_UUID" uuid NOT NULL,
|
||||
ts timestamp with time zone NOT NULL,
|
||||
value double precision
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE vmreports.vm_power_state OWNER TO dbo;
|
||||
|
||||
--
|
||||
-- TOC entry 4761 (class 2606 OID 9816998)
|
||||
-- Name: compute pk_compute; Type: CONSTRAINT; Schema: vmreports; Owner: smishchuk
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY vmreports.compute
|
||||
ADD CONSTRAINT pk_compute PRIMARY KEY (ts, "Object_UUID");
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 4759 (class 2606 OID 9816990)
|
||||
-- Name: host pk_host; Type: CONSTRAINT; Schema: vmreports; Owner: smishchuk
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY vmreports.host
|
||||
ADD CONSTRAINT pk_host PRIMARY KEY (ts, "Object_UUID");
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 4763 (class 2606 OID 9817010)
|
||||
-- Name: storage pk_storage; Type: CONSTRAINT; Schema: vmreports; Owner: smishchuk
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY vmreports.storage
|
||||
ADD CONSTRAINT pk_storage PRIMARY KEY (ts, "Object_UUID");
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 4767 (class 2606 OID 11093098)
|
||||
-- Name: vm_gpu pk_vm_gpu; Type: CONSTRAINT; Schema: vmreports; Owner: smishchuk
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY vmreports.vm_gpu
|
||||
ADD CONSTRAINT pk_vm_gpu PRIMARY KEY (ts, "Object_UUID");
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 4765 (class 2606 OID 11093091)
|
||||
-- Name: vm_power_state pk_vm_power_state; Type: CONSTRAINT; Schema: vmreports; Owner: smishchuk
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY vmreports.vm_power_state
|
||||
ADD CONSTRAINT pk_vm_power_state PRIMARY KEY ("Object_UUID", ts);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 5168 (class 0 OID 0)
|
||||
-- Dependencies: 10
|
||||
-- Name: SCHEMA vmreports; Type: ACL; Schema: -; Owner: dbo
|
||||
--
|
||||
|
||||
GRANT ALL ON SCHEMA vmreports TO nifi;
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
CREATE INDEX ON ngcloud_ru.capacity_resource (timestamp);
|
||||
CREATE INDEX ON ngcloud_ru.capacity_storage (timestamp);
|
||||
|
||||
CREATE INDEX ON s3billing.bucket_stat (timestamp_addition);
|
||||
CREATE INDEX ON s3billing.usage_bucket_by_user (time);
|
||||
|
||||
CREATE INDEX ON gpu.vm (dt_load);
|
||||
CREATE INDEX ON gpu.vm_power_state (ts);
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
ALTER TABLE IF EXISTS vmreports.storage
|
||||
OWNER to dbo;
|
||||
|
||||
REVOKE ALL ON TABLE vmreports.storage FROM analyst;
|
||||
REVOKE ALL ON TABLE vmreports.storage FROM analytics;
|
||||
REVOKE ALL ON TABLE vmreports.storage FROM appserver;
|
||||
|
||||
GRANT SELECT ON TABLE vmreports.storage TO analyst;
|
||||
|
||||
GRANT SELECT ON TABLE vmreports.storage TO analytics;
|
||||
|
||||
GRANT SELECT ON TABLE vmreports.storage TO appserver;
|
||||
|
||||
GRANT ALL ON TABLE vmreports.storage TO dbo;
|
||||
|
||||
GRANT ALL ON TABLE vmreports.storage TO designer;
|
||||
|
||||
GRANT ALL ON TABLE vmreports.storage TO nifi;
|
||||
|
||||
---------------
|
||||
ALTER TABLE IF EXISTS vmreports.compute
|
||||
OWNER to dbo;
|
||||
|
||||
REVOKE ALL ON TABLE vmreports.compute FROM analyst;
|
||||
REVOKE ALL ON TABLE vmreports.compute FROM analytics;
|
||||
REVOKE ALL ON TABLE vmreports.compute FROM appserver;
|
||||
|
||||
GRANT SELECT ON TABLE vmreports.compute TO analyst;
|
||||
|
||||
GRANT SELECT ON TABLE vmreports.compute TO analytics;
|
||||
|
||||
GRANT SELECT ON TABLE vmreports.compute TO appserver;
|
||||
|
||||
GRANT ALL ON TABLE vmreports.compute TO dbo;
|
||||
|
||||
GRANT ALL ON TABLE vmreports.compute TO designer;
|
||||
|
||||
GRANT ALL ON TABLE vmreports.compute TO nifi;
|
||||
|
||||
|
||||
--------------------
|
||||
ALTER TABLE IF EXISTS vmreports.host
|
||||
OWNER to dbo;
|
||||
|
||||
REVOKE ALL ON TABLE vmreports.host FROM analyst;
|
||||
REVOKE ALL ON TABLE vmreports.host FROM analytics;
|
||||
REVOKE ALL ON TABLE vmreports.host FROM appserver;
|
||||
|
||||
GRANT SELECT ON TABLE vmreports.host TO analyst;
|
||||
|
||||
GRANT SELECT ON TABLE vmreports.host TO analytics;
|
||||
|
||||
GRANT SELECT ON TABLE vmreports.host TO appserver;
|
||||
|
||||
GRANT ALL ON TABLE vmreports.host TO dbo;
|
||||
|
||||
GRANT ALL ON TABLE vmreports.host TO designer;
|
||||
|
||||
GRANT ALL ON TABLE vmreports.host TO nifi;
|
||||
|
||||
------------------------------------
|
||||
ALTER TABLE IF EXISTS vmreports.vm_gpu
|
||||
OWNER to dbo;
|
||||
|
||||
REVOKE ALL ON TABLE vmreports.vm_gpu FROM analyst;
|
||||
REVOKE ALL ON TABLE vmreports.vm_gpu FROM analytics;
|
||||
REVOKE ALL ON TABLE vmreports.vm_gpu FROM appserver;
|
||||
|
||||
GRANT SELECT ON TABLE vmreports.vm_gpu TO analyst;
|
||||
|
||||
GRANT SELECT ON TABLE vmreports.vm_gpu TO analytics;
|
||||
|
||||
GRANT SELECT ON TABLE vmreports.vm_gpu TO appserver;
|
||||
|
||||
GRANT ALL ON TABLE vmreports.vm_gpu TO dbo;
|
||||
|
||||
GRANT ALL ON TABLE vmreports.vm_gpu TO designer;
|
||||
|
||||
GRANT ALL ON TABLE vmreports.vm_gpu TO nifi;
|
||||
|
||||
-----------------
|
||||
ALTER TABLE IF EXISTS vmreports.vm_power_state
|
||||
OWNER to dbo;
|
||||
|
||||
REVOKE ALL ON TABLE vmreports.vm_power_state FROM analyst;
|
||||
REVOKE ALL ON TABLE vmreports.vm_power_state FROM analytics;
|
||||
REVOKE ALL ON TABLE vmreports.vm_power_state FROM appserver;
|
||||
|
||||
GRANT SELECT ON TABLE vmreports.vm_power_state TO analyst;
|
||||
|
||||
GRANT SELECT ON TABLE vmreports.vm_power_state TO analytics;
|
||||
|
||||
GRANT SELECT ON TABLE vmreports.vm_power_state TO appserver;
|
||||
|
||||
GRANT ALL ON TABLE vmreports.vm_power_state TO dbo;
|
||||
|
||||
GRANT ALL ON TABLE vmreports.vm_power_state TO designer;
|
||||
|
||||
GRANT ALL ON TABLE vmreports.vm_power_state TO nifi;
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
SET ROLE dbo;
|
||||
DROP SCHEMA IF EXISTS vmreports CASCADE;
|
||||
CREATE SCHEMA IF NOT EXISTS vmreports AUTHORIZATION dbo;
|
||||
|
||||
GRANT USAGE ON SCHEMA vmreports TO appserver;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT SELECT ON TABLES TO appserver;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT USAGE ON SEQUENCES TO appserver;
|
||||
|
||||
GRANT USAGE ON SCHEMA vmreports TO nifi,analytics,analyst;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT SELECT ON TABLES TO nifi,analytics,analyst;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT USAGE ON SEQUENCES TO nifi,analytics,analyst;
|
||||
|
||||
/*
|
||||
конструкция осложняется тем, что
|
||||
нужен один пользователь-владелец и второй читатель
|
||||
Это вызывает множество телодвижений при создании.
|
||||
Необходимость указывать пароль при локальном коннекте не очень радует
|
||||
(ведь пользователь локальный, прописан на этом же сервере)
|
||||
*/
|
||||
|
||||
--DROP FOREIGN TABLE IF EXISTS host;
|
||||
--CREATE FOREIGN TABLE vmreports.host () SERVER billing OPTIONS (schema_name 'vmreports', table_name 'host'); -- вместо этого лучше импортировать схему
|
||||
DROP SERVER IF EXISTS billing CASCADE;
|
||||
CREATE SERVER billing
|
||||
FOREIGN DATA WRAPPER postgres_fdw
|
||||
OPTIONS (host 'localhost', port '5432', dbname 'billing', updatable 'false');
|
||||
-- для импорта схемы мы создаем маппинг владельцу
|
||||
DROP USER MAPPING IF EXISTS FOR PUBLIC SERVER billing;
|
||||
CREATE USER MAPPING FOR PUBLIC SERVER billing OPTIONS (user 'appserver', password '***');
|
||||
|
||||
IMPORT FOREIGN SCHEMA vmreports FROM SERVER billing INTO vmreports;
|
||||
--GRANT SELECT ON vmreports.host to appserver;
|
||||
--DROP USER MAPPING IF EXISTS FOR dbo SERVER billing; -- мы импортировали схему, маппинг больше не нужен.
|
||||
-- Но нам все равно пришлось указать пароль дважды
|
||||
|
||||
|
||||
--DROP USER MAPPING IF EXISTS FOR appserver SERVER billing;
|
||||
--CREATE USER MAPPING FOR appserver SERVER billing OPTIONS (user 'nifi', password '***');
|
||||
--проверка
|
||||
--set role appserver; select * from vmreports.host;
|
||||
|
||||
-- это если интересно, не разрешен ли локальный коннект
|
||||
--SELECT * FROM pg_hba_file_rules;
|
||||
|
||||
/*
|
||||
Довольно тонкий нюанс, легко ускользающий
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE target_creator_role
|
||||
IN SCHEMA schema_name
|
||||
GRANT privilege_type ON TABLES TO recipient_role;
|
||||
Recommended Strategy for "Any User"Because there is no "FOR ALL ROLES" option, the best practice is to have all users create objects as a shared group role.Create a group role (e.g., schema_owner_role).Grant that role to all relevant users.Instruct users to run SET ROLE schema_owner_role; before creating objects.Run ALTER DEFAULT PRIVILEGES FOR ROLE schema_owner_role ... once to cover all objects created under that role.
|
||||
*/
|
||||
/*
|
||||
Best Practices for Role Owners:Dedicated Schema Owner: Create a dedicated, non-login role for managing database schema objects (DDL) and make it the owner of the database/schemas.Separation of Duties: Separate the application user (DML - SELECT, INSERT, UPDATE) from the owner role (DDL - CREATE, ALTER, DROP).Use ALTER DEFAULT PRIVILEGES: Set up default privileges for new objects to ensure that user roles automatically gain access to new tables or functions created by the owner role.Leverage Role Hierarchy: Create group roles (e.g., app_reader, app_writer) and grant these to individual user roles for easier permission management.Avoid Public Schema: Create specific schemas and revoke CREATE privileges on the public schema to prevent accidental object creation.Secure SUPERUSER Usage: Only use the default postgres superuser role for initial setup and critical administrative tasks. Never use it for applications.Example Implementation:sql-- Create a schema owner
|
||||
CREATE ROLE ddl_user NOLOGIN;
|
||||
-- Create an app user
|
||||
CREATE ROLE dml_user LOGIN PASSWORD 'secure_password';
|
||||
|
||||
-- Assign ownership
|
||||
ALTER DATABASE mydb OWNER TO ddl_user;
|
||||
ALTER SCHEMA public OWNER TO ddl_user;
|
||||
|
||||
-- Grant future access
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE ddl_user IN SCHEMA public
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO dml_user;
|
||||
*/
|
||||
@@ -0,0 +1,37 @@
|
||||
CREATE EXTENSION IF NOT EXISTS postgres_fdw;
|
||||
GRANT USAGE ON FOREIGN DATA WRAPPER postgres_fdw TO dbo;
|
||||
|
||||
SET ROLE dbo;
|
||||
DROP SCHEMA IF EXISTS vmreports CASCADE;
|
||||
CREATE SCHEMA IF NOT EXISTS vmreports AUTHORIZATION dbo;
|
||||
|
||||
GRANT USAGE ON SCHEMA vmreports TO nifi,analytics,analyst;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT SELECT ON TABLES TO nifi,analytics,analyst; -- это работает и для внешних таблиц
|
||||
--ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT USAGE ON SEQUENCES TO nifi,analytics,analyst;
|
||||
|
||||
/*
|
||||
конструкция осложняется тем, что
|
||||
нужен один пользователь-владелец и второй читатель
|
||||
Это вызывает множество телодвижений при создании.
|
||||
Необходимость указывать пароль при локальном коннекте не очень радует
|
||||
(ведь пользователь локальный, прописан на этом же сервере)
|
||||
*/
|
||||
|
||||
DROP SERVER IF EXISTS billing CASCADE;
|
||||
CREATE SERVER billing
|
||||
FOREIGN DATA WRAPPER postgres_fdw
|
||||
OPTIONS (host 'localhost', port '5432', dbname 'billing', updatable 'false');
|
||||
DROP USER MAPPING IF EXISTS FOR PUBLIC SERVER billing;
|
||||
CREATE USER MAPPING FOR PUBLIC SERVER billing OPTIONS (user 'nifi', password '***');
|
||||
|
||||
IMPORT FOREIGN SCHEMA vmreports FROM SERVER billing INTO vmreports;
|
||||
|
||||
--select * from vmreports.host;
|
||||
|
||||
/*
|
||||
план миграции
|
||||
Забекапить схему vmreports
|
||||
Восстановить схему vmreports в базу биллинг
|
||||
Поменять целевую базу импорта НиФи (для прода - втащить новый обмен из репозитория)
|
||||
Выполнить скрипт в базе DWH - он удалит физические таблицы и создаст внешние таблицы на базу billing
|
||||
*/
|
||||
@@ -0,0 +1,113 @@
|
||||
-- выполнить в базе dwh для создания внешних таблиц схемы vmreports
|
||||
-- перед выполнением забекапить схему vmreports для восстановления в БД billing
|
||||
CREATE EXTENSION IF NOT EXISTS postgres_fdw;
|
||||
GRANT USAGE ON FOREIGN DATA WRAPPER postgres_fdw TO dbo;
|
||||
|
||||
SET ROLE dbo;
|
||||
--DROP SCHEMA IF EXISTS vmreports CASCADE;
|
||||
CREATE SCHEMA IF NOT EXISTS vmreports AUTHORIZATION dbo;
|
||||
|
||||
GRANT USAGE ON SCHEMA vmreports TO nifi,analytics,analyst;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT SELECT ON TABLES TO nifi,analytics,analyst; -- это работает и для внешних таблиц
|
||||
--ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT USAGE ON SEQUENCES TO nifi,analytics,analyst;
|
||||
|
||||
/*
|
||||
конструкция осложняется тем, что
|
||||
нужен один пользователь-владелец и второй читатель
|
||||
Это вызывает множество телодвижений при создании.
|
||||
Необходимость указывать пароль при локальном коннекте не очень радует
|
||||
(ведь пользователь локальный, прописан на этом же сервере)
|
||||
А при смене его пароля все сломается, и поиск ошибки будет неочевиден
|
||||
*/
|
||||
|
||||
DO $$
|
||||
DECLARE
|
||||
rec RECORD;
|
||||
BEGIN
|
||||
FOR rec IN
|
||||
SELECT tablename
|
||||
FROM pg_tables
|
||||
WHERE schemaname = 'vmreports'
|
||||
LOOP
|
||||
EXECUTE format('ALTER TABLE vmreports.%I RENAME TO %I',
|
||||
rec.tablename,
|
||||
'del_' || rec.tablename);
|
||||
END LOOP;
|
||||
END $$;
|
||||
|
||||
DROP SERVER IF EXISTS billing CASCADE;
|
||||
CREATE SERVER billing
|
||||
FOREIGN DATA WRAPPER postgres_fdw
|
||||
OPTIONS (host 'localhost', port '5432', dbname 'billing', updatable 'false');
|
||||
DROP USER MAPPING IF EXISTS FOR PUBLIC SERVER billing;
|
||||
CREATE USER MAPPING FOR PUBLIC SERVER billing OPTIONS (user 'nifi', password '***');
|
||||
|
||||
IMPORT FOREIGN SCHEMA vmreports FROM SERVER billing INTO vmreports;
|
||||
|
||||
--select * from vmreports.host;
|
||||
|
||||
/*
|
||||
план миграции - черновик
|
||||
Забекапить схему vmreports
|
||||
Восстановить схему vmreports из бэкапа в базу биллинг
|
||||
Поменять целевую базу импорта НиФи (для прода - втащить новый обмен из репозитория)
|
||||
Выполнить скрипт в базе DWH - он удалит (переименует) физические таблицы и создаст внешние таблицы на базу billing
|
||||
*/
|
||||
|
||||
/*
|
||||
Исходно данные host, compute, storage, (gpu)
|
||||
загружались в dwh.vmreports,
|
||||
для анализа capacity
|
||||
|
||||
В текущей конфигурации,
|
||||
чтобы избежать дублирования
|
||||
таблиц, данных и обменов NiFi
|
||||
Направляем загрузку данных из VROPS в схему billing.vmreports
|
||||
и в базе dwh (схема vmreports) создаем Foreign Tables на billing.vmreports.
|
||||
-----------------------------------------------
|
||||
Миграция на проде:
|
||||
убедиться, что новый обмен VROPS->billing.vmreports (billing/vmReports) загружен в NiFi Registry
|
||||
найти пароль nifi (под ним коннект к localhost)
|
||||
остановить загрузку из VROPS на nifi-01 (billing/vmReports),
|
||||
сделать бэкап схемы dwh.vmreports (займет минут 10 ... заняло 215 сек),
|
||||
Восстановить схему vmreports в БД billing - запустить восстановление (Clean Before Restore) (РИСК: восстановление может занять много времени и завершиться с ошибками, обычно так бывает)
|
||||
select count (*) from vmreports.storage
|
||||
Выполнить этот скрипт (заменив пароль nifi на актуальный перед выполнением)
|
||||
переименовать таблицы из схемы vmreports для удаления (есть в скрипте выше)
|
||||
создать Foreign Tables (коннект проверится при импорте схемы)
|
||||
Проверить, что права назначились коррректно
|
||||
|
||||
Обновить обмен billing/vmReports на продуктиве, запустить
|
||||
-----------------------------------------------------------------
|
||||
Данные из billing.vmreports также реплицируются
|
||||
(процессорами группы LK)
|
||||
в буферную базу rpt
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
17:04:49 MSKERROR0dff1f93-153d-3a90-ed64-55d23960b88c
|
||||
EvaluateJsonPath[id=0dff1f93-153d-3a90-ed64-55d23960b88c] FlowFile FlowFile[filename=06c68bec-d824-4114-913b-bda34cb4fb1d] did not have valid JSON content.
|
||||
-- со второй попытки отработало
|
||||
17:05:15 MSKERROR239db407-76f2-3660-7fad-c4bedff6a4f8
|
||||
InvokeHTTP[id=239db407-76f2-3660-7fad-c4bedff6a4f8] Request Processing failed: FlowFile[filename=3474c340-f360-4a1e-a27e-283be41fc264]: java.net.SocketTimeoutException: timeout
|
||||
- Caused by: java.net.SocketException: Socket closed
|
||||
|
||||
https://payg.adl.nubes.ru/payg.cfm с первого раза таймаут, со второго посчиталось
|
||||
*/
|
||||
|
||||
/*
|
||||
теперь ищу в нифи примеры с кроном
|
||||
|
||||
17:25:05 MSKERROR16efa0f6-f1e7-3755-04fc-5be0383244ec
|
||||
PutDatabaseRecord[id=16efa0f6-f1e7-3755-04fc-5be0383244ec] Failed to put Records to database for FlowFile[filename=11f8176f-2a98-4199-932e-22e2fc2073b1]. Routing to failure.: org.apache.nifi.serialization.MalformedRecordException: Record does not have a value for the UpdateKey column 'obj_uuid'
|
||||
17:25:05 MSKERROR16efa0f6-f1e7-3755-04fc-5be0383244ec
|
||||
PutDatabaseRecord[id=16efa0f6-f1e7-3755-04fc-5be0383244ec] Record does not have a value for the UpdateKey column 'obj_uuid'
|
||||
17:25:05 MSKERROR16efa0f6-f1e7-3755-04fc-5be0383244ec
|
||||
PutDatabaseRecord[id=16efa0f6-f1e7-3755-04fc-5be0383244ec] Failed to put Records to database for FlowFile[filename=5039a3b6-2244-4451-81fc-deb8074f3cc7]. Routing to failure.: org.apache.nifi.serialization.MalformedRecordException: Record does not have a value for the UpdateKey column 'obj_uuid'
|
||||
17:25:05 MSKERROR16efa0f6-f1e7-3755-04fc-5be0383244ec
|
||||
PutDatabaseRecord[id=16efa0f6-f1e7-3755-04fc-5be0383244ec] Record does not have a value for the UpdateKey column 'obj_uuid'
|
||||
17:25:05 MSKERROR16efa0f6-f1e7-3755-04fc-5be0383244ec
|
||||
PutDatabaseRecord[id=16efa0f6-f1e7-3755-04fc-5be0383244ec] Failed to put Records to database for FlowFile[filename=8c6e9efb-198d-4303-897a-53fcfdf4d0f6]. Routing to failure.: org.apache.nifi.serialization.MalformedRecordException: Record does not have a value for the UpdateKey column 'obj_uuid'
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,47 @@
|
||||
SET ROLE dbo;
|
||||
DROP SCHEMA IF EXISTS vmreports CASCADE;
|
||||
CREATE SCHEMA IF NOT EXISTS vmreports AUTHORIZATION dbo;
|
||||
|
||||
--GRANT ALL ON SCHEMA vmreports TO postgres;
|
||||
BEGIN
|
||||
GRANT USAGE ON SCHEMA vmreports TO appserver;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT SELECT ON TABLES TO appserver;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT USAGE ON SEQUENCES TO appserver;
|
||||
EXCEPTION END;
|
||||
|
||||
BEGIN
|
||||
GRANT USAGE ON SCHEMA vmreports TO nifi,analytics,analyst;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT SELECT ON TABLES TO nifi,analytics,analyst;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE dbo IN SCHEMA vmreports GRANT USAGE ON SEQUENCES TO nifi,analytics,analyst;
|
||||
EXCEPTION WHEN others THEN END;
|
||||
/*
|
||||
конструкция осложняется тем, что
|
||||
нужен один пользователь-владелец и второй читатель
|
||||
Это вызывает множество телодвижений при создании.
|
||||
Необходимость указывать пароль при локальном коннекте не очень радует
|
||||
(ведь пользователь локальный, прописан на этом же сервере)
|
||||
*/
|
||||
|
||||
--DROP FOREIGN TABLE IF EXISTS host;
|
||||
--CREATE FOREIGN TABLE vmreports.host () SERVER billing OPTIONS (schema_name 'vmreports', table_name 'host'); -- вместо этого лучше импортировать схему
|
||||
DROP SERVER IF EXISTS billing CASCADE;
|
||||
CREATE SERVER billing
|
||||
FOREIGN DATA WRAPPER postgres_fdw
|
||||
OPTIONS (host 'localhost', port '5432', dbname 'billing');
|
||||
-- для импорта схемы мы создаем маппинг владельцу
|
||||
DROP USER MAPPING IF EXISTS FOR dbo SERVER billing;
|
||||
CREATE USER MAPPING FOR dbo SERVER billing OPTIONS (user 'appserver', password '***');
|
||||
|
||||
IMPORT FOREIGN SCHEMA vmreports FROM SERVER billing INTO vmreports;
|
||||
GRANT SELECT ON vmreports.host to appserver;
|
||||
DROP USER MAPPING IF EXISTS FOR dbo SERVER billing; -- мы импортировали схему, маппинг больше не нужен.
|
||||
-- Но нам все равно пришлось указать пароль дважды
|
||||
|
||||
|
||||
DROP USER MAPPING IF EXISTS FOR appserver SERVER billing;
|
||||
CREATE USER MAPPING FOR appserver SERVER billing OPTIONS (user 'appserver', password '***');
|
||||
--проверка
|
||||
--set role appserver; select * from vmreports.host;
|
||||
|
||||
-- это если интересно, не разрешен ли локальный коннект
|
||||
--SELECT * FROM pg_hba_file_rules;
|
||||
@@ -0,0 +1,52 @@
|
||||
SET ROLE dbo;
|
||||
DROP TABLE IF EXISTS vmreports.vsan_storage CASCADE;
|
||||
CREATE TABLE vmreports.vsan_storage (
|
||||
"Name" varchar(255) NULL,
|
||||
"ClusterNew" varchar(255) NULL,
|
||||
|
||||
"Total" float NULL,
|
||||
"Usable" float NULL,
|
||||
"Used" float NULL,
|
||||
"EffectiveFree" float NULL,
|
||||
|
||||
"Object_UUID" uuid NOT NULL,
|
||||
ts timestamptz NOT NULL
|
||||
,CONSTRAINT PK_vsan_storage PRIMARY KEY (ts, "Object_UUID")
|
||||
);
|
||||
--ALTER TABLE vmreports.vsan_storage OWNER TO dbo;
|
||||
GRANT ALL ON vmreports.vsan_storage TO nifi;
|
||||
--select * from vmreports.vsan_storage;
|
||||
|
||||
/*
|
||||
{
|
||||
"type": "record",
|
||||
"name": "vmreports.vsan_storage",
|
||||
"namespace": "org.apache.nifi",
|
||||
"fields": [
|
||||
{"name":"Object_UUID", "type":{"type": "string", "logicalType": "uuid"}},
|
||||
{"name":"ts","type":{"type": "long", "logicalType": "local-timestamp-millis"}},
|
||||
|
||||
{"name":"Name", "type":["string" ,"null"]},
|
||||
{"name":"ClusterNew", "type":["string" ,"null"]},
|
||||
|
||||
{"name":"Total", "type":["float" ,"null"]},
|
||||
{"name":"Usable", "type":["float" ,"null"]},
|
||||
{"name":"Used", "type":["float" ,"null"]},
|
||||
{"name":"EffectiveFree", "type":["float" ,"null"]}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
{
|
||||
"*": {
|
||||
"objId":"[&1].Name",
|
||||
"1":"[&1].ClusterNew",
|
||||
"2":"[&1].Total",
|
||||
"3":"[&1].Usable",
|
||||
"4":"[&1].Used",
|
||||
"5":"[&1].EffectiveFree",
|
||||
"objUUID":"[&1].Object_UUID"
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"ds_rpt_class": "org.postgresql.Driver",
|
||||
"ds_rpt_connectionString": "jdbc:postgresql://db-services.adl.nubes.ru:5432/dwh",
|
||||
"ds_rpt_username": "smishchuk",
|
||||
"ds_rpt_password": "encrypted:46692f9b4e3bda4931a9b83685a04a15187cb725295dc68627d7eb0b760362bc8a9de8d28395fca70b30fa4595cf3ed4a83772ee73eaf13a",
|
||||
"ds_rpt_connectionLimit": "5",
|
||||
"IDP_CLIENT_SECRET": "mXuJehst7ZZSBIFpjpLZFicYRhpLmxVs",
|
||||
}
|
||||
+633
@@ -0,0 +1,633 @@
|
||||
{
|
||||
"companyId": "1",
|
||||
"contracts": [
|
||||
{
|
||||
"contractId": "01983721-6049-72dd-a682-a5af1bd72420",
|
||||
"contractInsideId": "02319_1",
|
||||
"contractOutsideId": "02319_1",
|
||||
"contractStartDate": "20250801",
|
||||
"isContractTerminated": false,
|
||||
"CalculationPeriod": "20260701",
|
||||
"additionalAgreements": [
|
||||
{
|
||||
"additionalAgreementId": "019b6ec1-1984-78fc-9e48-0984aa1f3ca7",
|
||||
"additionalAgreementIndex": 3,
|
||||
"additionalAgreementName": "Доп соглашение 3, к сделке №3768 Сделка на изменения договора",
|
||||
"additionalAgreementStartDate": "",
|
||||
"additionalAgreementBaseBy": "019a5ef8-eebe-76b3-acb9-b5c37748f4ef",
|
||||
"isActual": true,
|
||||
"CalculationPeriod": "20260701",
|
||||
"services": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"paramId": 118,
|
||||
"componentCode": "paas.s3.ceph.vol",
|
||||
"component": "Дисковое пространство: Объем хранения",
|
||||
"measureShort": "ГБайт",
|
||||
"quantity": 1,
|
||||
"priceWVat": 1.8300000000000001,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.ceph.vol"
|
||||
},
|
||||
{
|
||||
"paramId": 69,
|
||||
"componentCode": "paas.s3.ceph.trf",
|
||||
"component": "Исходящий трафик",
|
||||
"measureShort": "ГБайт",
|
||||
"quantity": 1,
|
||||
"priceWVat": 1.5249999999999999,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.ceph.trf"
|
||||
},
|
||||
{
|
||||
"paramId": 68,
|
||||
"componentCode": "paas.s3.ceph.get",
|
||||
"component": "Запросы GET, HEAD, OPTIONS",
|
||||
"measureShort": "10тыс.шт.",
|
||||
"quantity": 1,
|
||||
"priceWVat": 0.3538,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.ceph.get"
|
||||
},
|
||||
{
|
||||
"paramId": 70,
|
||||
"componentCode": "paas.s3.ceph.put",
|
||||
"component": "Запросы PUT, POST, PATCH, LIST",
|
||||
"measureShort": "10тыс.шт.",
|
||||
"quantity": 1,
|
||||
"priceWVat": 4.5750000000000002,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.ceph.put"
|
||||
}
|
||||
],
|
||||
"staticId": "e57bb0bd-8946-4603-95e8-c9c331378bce",
|
||||
"serviceId": "2e1681d7-542e-489c-9169-de562bdca83a",
|
||||
"serviceHash": "e57bb0bd-8946-4603-95e8-c9c331378bce3",
|
||||
"LineCRMID": "019b6ec6-a779-7902-abeb-d2f7e746d64e",
|
||||
"serviceCode": "paas.s3.ceph",
|
||||
"endCustomerName": "",
|
||||
"endCustomerINN": "",
|
||||
"catalogName": "Объектное хранилище",
|
||||
"discount": 0.24125452,
|
||||
"quantity": 1,
|
||||
"dateStartProvision": "20260101",
|
||||
"dateEndProvision": "",
|
||||
"serviceStart": {
|
||||
"currentTimeZoneName": "UTC",
|
||||
"ts": "2026-01-01T00:00:00.000Z"
|
||||
},
|
||||
"serviceCustomName": "Объектное хранилище: S3 CEPH, в составе:\n Дисковое пространство: Объем хранения - 1 ГБайт\nИсходящий трафик - 1 ГБайт\nЗапросы GET, HEAD, OPTIONS - 1 10тыс.шт.\nЗапросы PUT, POST, PATCH, LIST - 1 10тыс.шт.\n",
|
||||
"serviceType": 3,
|
||||
"service_is_easy": false,
|
||||
"vat": 22,
|
||||
"vatRate": 0.22,
|
||||
"vatPerc": 22,
|
||||
"vatFree": 0,
|
||||
"priceWVat": "",
|
||||
"serviceVersionGuid": "2e1681d7-542e-489c-9169-de562bdca83a",
|
||||
"dealIndex": 3768,
|
||||
"CalculationPeriod": "20260701"
|
||||
},
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"paramId": 118,
|
||||
"componentCode": "paas.s3.cphc.vol",
|
||||
"component": "Дисковое пространство: Объем хранения",
|
||||
"measureShort": "ГБайт",
|
||||
"quantity": 1,
|
||||
"priceWVat": 1.026833333333,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.cphc.vol"
|
||||
},
|
||||
{
|
||||
"paramId": 69,
|
||||
"componentCode": "paas.s3.cphc.trf",
|
||||
"component": "Исходящий трафик",
|
||||
"measureShort": "ГБайт",
|
||||
"quantity": 1,
|
||||
"priceWVat": 1.5249999999999999,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.cphc.trf"
|
||||
},
|
||||
{
|
||||
"paramId": 68,
|
||||
"componentCode": "paas.s3.cphc.get",
|
||||
"component": "Запросы GET, HEAD, OPTIONS",
|
||||
"measureShort": "10тыс.шт.",
|
||||
"quantity": 1,
|
||||
"priceWVat": 0.97599999999999998,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.cphc.get"
|
||||
},
|
||||
{
|
||||
"paramId": 70,
|
||||
"componentCode": "paas.s3.cphc.put",
|
||||
"component": "Запросы PUT, POST, PATCH, LIST",
|
||||
"measureShort": "10тыс.шт.",
|
||||
"quantity": 1,
|
||||
"priceWVat": 11.834,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.cphc.put"
|
||||
}
|
||||
],
|
||||
"staticId": "2031f3ac-e921-4816-b91f-9b5b1cf5bf94",
|
||||
"serviceId": "5271dc39-2ec5-4f20-b91e-fdffb4f363b9",
|
||||
"serviceHash": "2031f3ac-e921-4816-b91f-9b5b1cf5bf943",
|
||||
"LineCRMID": "019b6ec6-a82c-7902-93a3-48ba4e25d71d",
|
||||
"serviceCode": "paas.s3.cphc",
|
||||
"endCustomerName": "",
|
||||
"endCustomerINN": "",
|
||||
"catalogName": "Объектное хранилище",
|
||||
"discount": 0,
|
||||
"quantity": 1,
|
||||
"dateStartProvision": "20260101",
|
||||
"dateEndProvision": "",
|
||||
"serviceStart": {
|
||||
"currentTimeZoneName": "UTC",
|
||||
"ts": "2026-01-01T00:00:00.000Z"
|
||||
},
|
||||
"serviceCustomName": "Объектное хранилище: S3 CEPH Холодное, в составе:\n Дисковое пространство: Объем хранения - 1 ГБайт\nИсходящий трафик - 1 ГБайт\nЗапросы GET, HEAD, OPTIONS - 1 10тыс.шт.\nЗапросы PUT, POST, PATCH, LIST - 1 10тыс.шт.\n",
|
||||
"serviceType": 3,
|
||||
"service_is_easy": false,
|
||||
"vat": 22,
|
||||
"vatRate": 0.22,
|
||||
"vatPerc": 22,
|
||||
"vatFree": 0,
|
||||
"priceWVat": "",
|
||||
"serviceVersionGuid": "5271dc39-2ec5-4f20-b91e-fdffb4f363b9",
|
||||
"dealIndex": 3768,
|
||||
"CalculationPeriod": "20260701"
|
||||
},
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"paramId": 175,
|
||||
"componentCode": "paas.s3.cphc.volq",
|
||||
"component": "Дисковое пространство: Квота",
|
||||
"measureShort": "ГБайт",
|
||||
"quantity": 1,
|
||||
"priceWVat": 2.7999999999999998,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.cphc.volq"
|
||||
}
|
||||
],
|
||||
"staticId": "f216f0ac-6c61-42aa-a454-56a93c707d11",
|
||||
"serviceId": "776a3490-cb3a-4721-b521-7bf97073e104",
|
||||
"serviceHash": "f216f0ac-6c61-42aa-a454-56a93c707d112",
|
||||
"LineCRMID": "019b6ec6-a86d-7902-9ba2-defe46f2a036",
|
||||
"serviceCode": "paas.s3.cphc",
|
||||
"endCustomerName": "",
|
||||
"endCustomerINN": "",
|
||||
"catalogName": "Объектное хранилище",
|
||||
"discount": 63.928570999999998,
|
||||
"quantity": 1000,
|
||||
"dateStartProvision": "20250826",
|
||||
"dateEndProvision": "20250930",
|
||||
"serviceStart": {
|
||||
"currentTimeZoneName": "UTC",
|
||||
"ts": "2025-08-26T00:00:00.000Z"
|
||||
},
|
||||
"serviceEnd": {
|
||||
"currentTimeZoneName": "UTC",
|
||||
"ts": "2025-09-30T00:00:00.000Z"
|
||||
},
|
||||
"serviceCustomName": "Объектное хранилище: S3 CEPH Холодное (Квота), в составе:\n Дисковое пространство: Квота - 1 ГБайт\n",
|
||||
"serviceType": 2,
|
||||
"service_is_easy": false,
|
||||
"vat": 20,
|
||||
"vatRate": 0.20000000000000001,
|
||||
"vatPerc": 20,
|
||||
"vatFree": 0,
|
||||
"priceWVat": "",
|
||||
"serviceVersionGuid": "776a3490-cb3a-4721-b521-7bf97073e104",
|
||||
"dealIndex": 3768,
|
||||
"CalculationPeriod": "20260701"
|
||||
},
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"paramId": 175,
|
||||
"componentCode": "paas.s3.cphc.volq",
|
||||
"component": "Дисковое пространство: Квота",
|
||||
"measureShort": "ГБайт",
|
||||
"quantity": 1,
|
||||
"priceWVat": 2.7999999999999998,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.cphc.volq"
|
||||
}
|
||||
],
|
||||
"staticId": "78707549-a675-46e0-bc5b-790ef4d21b6d",
|
||||
"serviceId": "2e9369bc-7f3e-4c31-bb72-3d19e979964e",
|
||||
"serviceHash": "78707549-a675-46e0-bc5b-790ef4d21b6d2",
|
||||
"LineCRMID": "019b6ec6-a8ab-7902-af73-1034bf013a16",
|
||||
"serviceCode": "paas.s3.cphc",
|
||||
"endCustomerName": "",
|
||||
"endCustomerINN": "",
|
||||
"catalogName": "Объектное хранилище",
|
||||
"discount": 63.928570999999998,
|
||||
"quantity": 40000,
|
||||
"dateStartProvision": "20250826",
|
||||
"dateEndProvision": "20250930",
|
||||
"serviceStart": {
|
||||
"currentTimeZoneName": "UTC",
|
||||
"ts": "2025-08-26T00:00:00.000Z"
|
||||
},
|
||||
"serviceEnd": {
|
||||
"currentTimeZoneName": "UTC",
|
||||
"ts": "2025-09-30T00:00:00.000Z"
|
||||
},
|
||||
"serviceCustomName": "Объектное хранилище: S3 CEPH Холодное (Квота), в составе:\n Дисковое пространство: Квота - 1 ГБайт\n",
|
||||
"serviceType": 2,
|
||||
"service_is_easy": false,
|
||||
"vat": 20,
|
||||
"vatRate": 0.20000000000000001,
|
||||
"vatPerc": 20,
|
||||
"vatFree": 0,
|
||||
"priceWVat": "",
|
||||
"serviceVersionGuid": "2e9369bc-7f3e-4c31-bb72-3d19e979964e",
|
||||
"dealIndex": 3768,
|
||||
"CalculationPeriod": "20260701"
|
||||
},
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"paramId": 118,
|
||||
"componentCode": "paas.s3.cphc.vol",
|
||||
"component": "Дисковое пространство: Объем хранения",
|
||||
"measureShort": "ГБайт",
|
||||
"quantity": 1,
|
||||
"priceWVat": 1.01,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.cphc.vol"
|
||||
},
|
||||
{
|
||||
"paramId": 69,
|
||||
"componentCode": "paas.s3.cphc.trf",
|
||||
"component": "Исходящий трафик",
|
||||
"measureShort": "ГБайт",
|
||||
"quantity": 1,
|
||||
"priceWVat": 1.5,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.cphc.trf"
|
||||
},
|
||||
{
|
||||
"paramId": 68,
|
||||
"componentCode": "paas.s3.cphc.get",
|
||||
"component": "Запросы GET, HEAD, OPTIONS",
|
||||
"measureShort": "10тыс.шт.",
|
||||
"quantity": 1,
|
||||
"priceWVat": 0.95999999999999996,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.cphc.get"
|
||||
},
|
||||
{
|
||||
"paramId": 70,
|
||||
"componentCode": "paas.s3.cphc.put",
|
||||
"component": "Запросы PUT, POST, PATCH",
|
||||
"measureShort": "10тыс.шт.",
|
||||
"quantity": 1,
|
||||
"priceWVat": 11.640000000000001,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.cphc.put"
|
||||
}
|
||||
],
|
||||
"staticId": "20240911T125603868",
|
||||
"serviceId": "a564eda1-b716-42ca-9ae7-efc49b112a58",
|
||||
"serviceHash": "20240911T1256038683",
|
||||
"LineCRMID": "019b6ec6-a949-7902-b473-8741f2a18efa",
|
||||
"serviceCode": "paas.s3.cphc",
|
||||
"endCustomerName": "",
|
||||
"endCustomerINN": "",
|
||||
"catalogName": "Объектное хранилище",
|
||||
"discount": 0,
|
||||
"quantity": 1,
|
||||
"dateStartProvision": "20250826",
|
||||
"dateEndProvision": "20250930",
|
||||
"serviceStart": {
|
||||
"currentTimeZoneName": "UTC",
|
||||
"ts": "2025-08-26T00:00:00.000Z"
|
||||
},
|
||||
"serviceEnd": {
|
||||
"currentTimeZoneName": "UTC",
|
||||
"ts": "2025-09-30T00:00:00.000Z"
|
||||
},
|
||||
"serviceCustomName": "Объектное хранилище: S3 CEPH Холодное, в составе:\n Дисковое пространство: Объем хранения - 1 ГБайт\nИсходящий трафик - 1 ГБайт\nЗапросы GET, HEAD, OPTIONS - 1 10тыс.шт.\nЗапросы PUT, POST, PATCH - 1 10тыс.шт.\n",
|
||||
"serviceType": 3,
|
||||
"service_is_easy": false,
|
||||
"vat": 20,
|
||||
"vatRate": 0.20000000000000001,
|
||||
"vatPerc": 20,
|
||||
"vatFree": 0,
|
||||
"priceWVat": "",
|
||||
"serviceVersionGuid": "a564eda1-b716-42ca-9ae7-efc49b112a58",
|
||||
"dealIndex": 3768,
|
||||
"CalculationPeriod": "20260701"
|
||||
},
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"paramId": 118,
|
||||
"componentCode": "paas.s3.ceph.vol",
|
||||
"component": "Дисковое пространство: Объем хранения",
|
||||
"measureShort": "ГБайт",
|
||||
"quantity": 1,
|
||||
"priceWVat": 1.8,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.ceph.vol"
|
||||
},
|
||||
{
|
||||
"paramId": 69,
|
||||
"componentCode": "paas.s3.ceph.trf",
|
||||
"component": "Исходящий трафик",
|
||||
"measureShort": "ГБайт",
|
||||
"quantity": 1,
|
||||
"priceWVat": 1.5,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.ceph.trf"
|
||||
},
|
||||
{
|
||||
"paramId": 68,
|
||||
"componentCode": "paas.s3.ceph.get",
|
||||
"component": "Запросы GET, HEAD, OPTIONS",
|
||||
"measureShort": "10тыс.шт.",
|
||||
"quantity": 1,
|
||||
"priceWVat": 0.34999999999999998,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.ceph.get"
|
||||
},
|
||||
{
|
||||
"paramId": 70,
|
||||
"componentCode": "paas.s3.ceph.put",
|
||||
"component": "Запросы PUT, POST, PATCH",
|
||||
"measureShort": "10тыс.шт.",
|
||||
"quantity": 1,
|
||||
"priceWVat": 4.5,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.ceph.put"
|
||||
}
|
||||
],
|
||||
"staticId": "20241015T124353835",
|
||||
"serviceId": "5371b7cb-6f6c-4c7d-85b4-609eb52f994a",
|
||||
"serviceHash": "20241015T1243538353",
|
||||
"LineCRMID": "019b6ec6-aa03-7902-9c40-06f6d5cf6e13",
|
||||
"serviceCode": "paas.s3.ceph",
|
||||
"endCustomerName": "",
|
||||
"endCustomerINN": "",
|
||||
"catalogName": "Объектное хранилище",
|
||||
"discount": 0,
|
||||
"quantity": 1,
|
||||
"dateStartProvision": "20250801",
|
||||
"dateEndProvision": "20250930",
|
||||
"serviceStart": {
|
||||
"currentTimeZoneName": "UTC",
|
||||
"ts": "2025-08-01T00:00:00.000Z"
|
||||
},
|
||||
"serviceEnd": {
|
||||
"currentTimeZoneName": "UTC",
|
||||
"ts": "2025-09-30T00:00:00.000Z"
|
||||
},
|
||||
"serviceCustomName": "Объектное хранилище: S3 CEPH, в составе:\n Дисковое пространство: Объем хранения - 1 ГБайт\nИсходящий трафик - 1 ГБайт\nЗапросы GET, HEAD, OPTIONS - 1 10тыс.шт.\nЗапросы PUT, POST, PATCH - 1 10тыс.шт.\n",
|
||||
"serviceType": 3,
|
||||
"service_is_easy": false,
|
||||
"vat": 20,
|
||||
"vatRate": 0.20000000000000001,
|
||||
"vatPerc": 20,
|
||||
"vatFree": 0,
|
||||
"priceWVat": "",
|
||||
"serviceVersionGuid": "5371b7cb-6f6c-4c7d-85b4-609eb52f994a",
|
||||
"dealIndex": 3768,
|
||||
"CalculationPeriod": "20260701"
|
||||
},
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"paramId": 69,
|
||||
"componentCode": "paas.s3.ceph.trf",
|
||||
"component": "Исходящий трафик",
|
||||
"measureShort": "ГБайт",
|
||||
"quantity": 1,
|
||||
"priceWVat": 1.5,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.ceph.trf"
|
||||
},
|
||||
{
|
||||
"paramId": 70,
|
||||
"componentCode": "paas.s3.ceph.put",
|
||||
"component": "Запросы PUT, POST, PATCH, LIST",
|
||||
"measureShort": "10тыс.шт.",
|
||||
"quantity": 1,
|
||||
"priceWVat": 4.5,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.ceph.put"
|
||||
},
|
||||
{
|
||||
"paramId": 118,
|
||||
"componentCode": "paas.s3.ceph.vol",
|
||||
"component": "Дисковое пространство: Объем хранения",
|
||||
"measureShort": "ГБайт",
|
||||
"quantity": 1,
|
||||
"priceWVat": 1.8,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.ceph.vol"
|
||||
},
|
||||
{
|
||||
"paramId": 68,
|
||||
"componentCode": "paas.s3.ceph.get",
|
||||
"component": "Запросы GET, HEAD, OPTIONS",
|
||||
"measureShort": "10тыс.шт.",
|
||||
"quantity": 1,
|
||||
"priceWVat": 0.34999999999999998,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.ceph.get"
|
||||
}
|
||||
],
|
||||
"staticId": "e57bb0bd-8946-4603-95e8-c9c331378bce",
|
||||
"serviceId": "09fd617a-9ffc-4b98-ad66-3fedac52c7b9",
|
||||
"serviceHash": "e57bb0bd-8946-4603-95e8-c9c331378bce3",
|
||||
"LineCRMID": "019a732b-22a2-7545-91ce-819207c779a0",
|
||||
"catalogName": "Объектное хранилище",
|
||||
"endCustomerName": "",
|
||||
"endCustomerINN": "",
|
||||
"serviceCode": "paas.s3.ceph",
|
||||
"discount": 0,
|
||||
"quantity": 1,
|
||||
"dateStartProvision": "20251001",
|
||||
"CalculationPeriod": "20260701",
|
||||
"dateEndProvision": "20251231",
|
||||
"serviceStart": {
|
||||
"currentTimeZoneName": "UTC",
|
||||
"ts": "2025-10-01T00:00:00.000Z"
|
||||
},
|
||||
"serviceEnd": {
|
||||
"currentTimeZoneName": "UTC",
|
||||
"ts": "2025-12-31T00:00:00.000Z"
|
||||
},
|
||||
"serviceCustomName": "Объектное хранилище: S3 CEPH, в составе:\n Исходящий трафик - 1 ГБайт\nЗапросы PUT, POST, PATCH, LIST - 1 10тыс.шт.\nДисковое пространство: Объем хранения - 1 ГБайт\nЗапросы GET, HEAD, OPTIONS - 1 10тыс.шт.\n",
|
||||
"serviceType": 3,
|
||||
"service_is_easy": false,
|
||||
"vat": 20,
|
||||
"vatRate": 0.20000000000000001,
|
||||
"vatPerc": 20,
|
||||
"vatFree": 0,
|
||||
"priceWVat": "",
|
||||
"serviceVersionGuid": "09fd617a-9ffc-4b98-ad66-3fedac52c7b9",
|
||||
"dealIndex": 3274
|
||||
},
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"paramId": 118,
|
||||
"componentCode": "paas.s3.cphc.vol",
|
||||
"component": "Дисковое пространство: Объем хранения",
|
||||
"measureShort": "ГБайт",
|
||||
"quantity": 1,
|
||||
"priceWVat": 1.01,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.cphc.vol"
|
||||
},
|
||||
{
|
||||
"paramId": 69,
|
||||
"componentCode": "paas.s3.cphc.trf",
|
||||
"component": "Исходящий трафик",
|
||||
"measureShort": "ГБайт",
|
||||
"quantity": 1,
|
||||
"priceWVat": 1.5,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.cphc.trf"
|
||||
},
|
||||
{
|
||||
"paramId": 68,
|
||||
"componentCode": "paas.s3.cphc.get",
|
||||
"component": "Запросы GET, HEAD, OPTIONS",
|
||||
"measureShort": "10тыс.шт.",
|
||||
"quantity": 1,
|
||||
"priceWVat": 0.95999999999999996,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.cphc.get"
|
||||
},
|
||||
{
|
||||
"paramId": 70,
|
||||
"componentCode": "paas.s3.cphc.put",
|
||||
"component": "Запросы PUT, POST, PATCH, LIST",
|
||||
"measureShort": "10тыс.шт.",
|
||||
"quantity": 1,
|
||||
"priceWVat": 11.640000000000001,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.cphc.put"
|
||||
}
|
||||
],
|
||||
"staticId": "2031f3ac-e921-4816-b91f-9b5b1cf5bf94",
|
||||
"serviceId": "539d210f-2e5a-45e2-b148-b0b0834c138c",
|
||||
"serviceHash": "2031f3ac-e921-4816-b91f-9b5b1cf5bf943",
|
||||
"LineCRMID": "019a732b-22d4-7545-83af-18b7f8867eaa",
|
||||
"catalogName": "Объектное хранилище",
|
||||
"endCustomerName": "",
|
||||
"endCustomerINN": "",
|
||||
"serviceCode": "paas.s3.cphc",
|
||||
"discount": 0,
|
||||
"quantity": 1,
|
||||
"dateStartProvision": "20251001",
|
||||
"CalculationPeriod": "20260701",
|
||||
"dateEndProvision": "20251231",
|
||||
"serviceStart": {
|
||||
"currentTimeZoneName": "UTC",
|
||||
"ts": "2025-10-01T00:00:00.000Z"
|
||||
},
|
||||
"serviceEnd": {
|
||||
"currentTimeZoneName": "UTC",
|
||||
"ts": "2025-12-31T00:00:00.000Z"
|
||||
},
|
||||
"serviceCustomName": "Объектное хранилище: S3 CEPH Холодное, в составе:\n Дисковое пространство: Объем хранения - 1 ГБайт\nИсходящий трафик - 1 ГБайт\nЗапросы GET, HEAD, OPTIONS - 1 10тыс.шт.\nЗапросы PUT, POST, PATCH, LIST - 1 10тыс.шт.\n",
|
||||
"serviceType": 3,
|
||||
"service_is_easy": false,
|
||||
"vat": 20,
|
||||
"vatRate": 0.20000000000000001,
|
||||
"vatPerc": 20,
|
||||
"vatFree": 0,
|
||||
"priceWVat": "",
|
||||
"serviceVersionGuid": "539d210f-2e5a-45e2-b148-b0b0834c138c",
|
||||
"dealIndex": 3274
|
||||
},
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"paramId": 118,
|
||||
"componentCode": "paas.s3.cphc.vol",
|
||||
"component": "Дисковое пространство: Объем хранения",
|
||||
"measureShort": "ГБайт",
|
||||
"quantity": 40000,
|
||||
"priceWVat": 1.01,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.cphc.vol"
|
||||
},
|
||||
{
|
||||
"paramId": 68,
|
||||
"componentCode": "paas.s3.cphc.get",
|
||||
"component": "Запросы GET, HEAD, OPTIONS",
|
||||
"measureShort": "10тыс.шт.",
|
||||
"quantity": 1,
|
||||
"priceWVat": 0.95999999999999996,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.cphc.get"
|
||||
},
|
||||
{
|
||||
"paramId": 69,
|
||||
"componentCode": "paas.s3.cphc.trf",
|
||||
"component": "Исходящий трафик",
|
||||
"measureShort": "ГБайт",
|
||||
"quantity": 1,
|
||||
"priceWVat": 1.5,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.cphc.trf"
|
||||
},
|
||||
{
|
||||
"paramId": 70,
|
||||
"componentCode": "paas.s3.cphc.put",
|
||||
"component": "Запросы PUT, POST, PATCH",
|
||||
"measureShort": "10тыс.шт.",
|
||||
"quantity": 1,
|
||||
"priceWVat": 11.640000000000001,
|
||||
"discount": 0,
|
||||
"atomicCode": "paas.s3.cphc.put"
|
||||
}
|
||||
],
|
||||
"staticId": "20240911T125603868",
|
||||
"serviceId": "67dffa20-a69e-449a-b02c-edf78d9ff192",
|
||||
"serviceHash": "20240911T1256038683",
|
||||
"LineCRMID": "01983726-3501-7496-b7f3-6f58f4d7f209",
|
||||
"catalogName": "Объектное хранилище",
|
||||
"endCustomerName": "",
|
||||
"endCustomerINN": "",
|
||||
"serviceCode": "paas.s3.cphc",
|
||||
"discount": 0,
|
||||
"quantity": 1,
|
||||
"dateStartProvision": "20250801",
|
||||
"CalculationPeriod": "20260701",
|
||||
"dateEndProvision": "20250825",
|
||||
"serviceStart": {
|
||||
"currentTimeZoneName": "UTC",
|
||||
"ts": "2025-08-01T00:00:00.000Z"
|
||||
},
|
||||
"serviceEnd": {
|
||||
"currentTimeZoneName": "UTC",
|
||||
"ts": "2025-08-25T00:00:00.000Z"
|
||||
},
|
||||
"serviceCustomName": "Объектное хранилище: S3 CEPH Холодное, в составе:\n Дисковое пространство: Объем хранения - 40000 ГБайт\nЗапросы GET, HEAD, OPTIONS - 1 10тыс.шт.\nИсходящий трафик - 1 ГБайт\nЗапросы PUT, POST, PATCH - 1 10тыс.шт.\n",
|
||||
"serviceType": 3,
|
||||
"service_is_easy": false,
|
||||
"vat": 20,
|
||||
"vatRate": 0.20000000000000001,
|
||||
"vatPerc": 20,
|
||||
"vatFree": 0,
|
||||
"priceWVat": "",
|
||||
"serviceVersionGuid": "67dffa20-a69e-449a-b02c-edf78d9ff192",
|
||||
"dealIndex": 1450
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
REM set Windows env
|
||||
setx rpt_class org.postgresql.Driver /M
|
||||
setx rpt_connectionString jdbc:postgresql://write.09d78921-77a7-401a-b2cb-5ca11be850a0.services.ngcloud.ru:5432/rpt /M
|
||||
setx rpt_username appserver /M
|
||||
setx rpt_password encrypted:8b11c6e220c6456af3e08294e86cf91283d4119b58e25891e24719b0d27cbd4991d023c88da45113555c98d2cb5e4e969a4f585a94051527 /M
|
||||
setx rpt_connectionLimit 5 /M
|
||||
|
||||
setx IDP_CLIENT_SECRET mXuJehst7ZZSBIFpjpLZFicYRhpLmxVs /M
|
||||
|
||||
pause
|
||||
@@ -1,10 +0,0 @@
|
||||
REM set Windows env
|
||||
setx rpt_class org.postgresql.Driver /M
|
||||
setx rpt_connectionString jdbc:postgresql://write.09d78921-77a7-401a-b2cb-5ca11be850a0.services.ngcloud.ru:5432/rpt /M
|
||||
setx rpt_username smishchuk /M
|
||||
setx rpt_password encrypted:8b11c6e220c6456af3e08294e86cf91283d4119b58e25891e24719b0d27cbd4991d023c88da45113555c98d2cb5e4e969a4f585a94051527 /M
|
||||
setx rpt_connectionLimit 5 /M
|
||||
|
||||
setx IDP_CLIENT_SECRET mXuJehst7ZZSBIFpjpLZFicYRhpLmxVs /M
|
||||
|
||||
pause
|
||||
@@ -1,10 +0,0 @@
|
||||
REM set Windows env
|
||||
setx rpt_class org.postgresql.Driver /M
|
||||
setx rpt_connectionString jdbc:postgresql://write.09d78921-77a7-401a-b2cb-5ca11be850a0.services.ngcloud.ru:5432/rpt /M
|
||||
setx rpt_username smishchuk /M
|
||||
setx rpt_password encrypted:******** /M
|
||||
setx rpt_connectionLimit 5 /M
|
||||
|
||||
setx IDP_CLIENT_SECRET ******** /M
|
||||
|
||||
pause
|
||||
@@ -0,0 +1,159 @@
|
||||
<cfsilent>
|
||||
<cfimport prefix="m" taglib="lib"/>
|
||||
<cfimport prefix="c" taglib="lib/controls"/>
|
||||
<cfimport prefix="d" taglib="lib/data"/>
|
||||
<cfimport prefix="layout" taglib="layout"/>
|
||||
</cfsilent>
|
||||
|
||||
<m:prepare_ls entity="payg" accessObject="" pageInfoOut="pageInfo" trackOut="tr"/>
|
||||
|
||||
<cfparam name="dt_finish" type="date" default=#createDateTime(year(Now()),month(Now()),1,0,0,0)#/>
|
||||
<cfparam name="dt_start" type="date" default=#dateAdd('m',-1,dt_finish)#/>
|
||||
<cfset hours=dateDiff('h',dt_start,dt_finish)/>
|
||||
<cfset tenant_wz_index=val(mid(request.auth.wz,3,5))/><!--- cut off WZ --->
|
||||
<cfset tenant_wz_index="00169"/><!--- cut off WZ --->
|
||||
|
||||
|
||||
<cfif isDefined("output_xls")><cfmodule template="mod/payg.cfm"
|
||||
dt_finish=#dt_finish#
|
||||
dt_start=#dt_start#
|
||||
tenant_wz_index=#tenant_wz_index#
|
||||
output="report"
|
||||
debug=#isDefined("DEBUG")#
|
||||
/><layout:xml qRead=#report.qCharge# titleMap=#report.chargeTitleMap# filename="#pageInfo.entity#.xml"/>
|
||||
<cfabort/>
|
||||
</cfif><cfif isDefined("output_json")><cfmodule template="mod/payg.cfm"
|
||||
dt_finish=#dt_finish#
|
||||
dt_start=#dt_start#
|
||||
tenant_wz_index=#tenant_wz_index#
|
||||
output="report"
|
||||
debug=#isDefined("DEBUG")#
|
||||
/><!--- <cfdump var=#report#/><cfabort/> ---><layout:json qRead=#report.qCharge# titleMap=#report.chargeTitleMap# filename="#pageInfo.entity#.json"/>
|
||||
<cfabort/>
|
||||
</cfif><!---
|
||||
---><layout:page section="header" pageInfo=#pageInfo#>
|
||||
|
||||
<layout:attribute name="title">
|
||||
<cfoutput><b>Отчет по PAYG</b> #request.auth.wz#</cfoutput>
|
||||
</layout:attribute>
|
||||
<layout:attribute name="controls">
|
||||
<!---skip filter link, filter is not implemented--->
|
||||
<!---<layout:language_switch/>--->
|
||||
</layout:attribute>
|
||||
</layout:page>
|
||||
|
||||
<!--- Внимание! округление вверх при расчете метрик get, put S3. Расчетные суммы могут содержать погрешности округления, поэтому окончательный расчет стоимости (количество * цену) должен выполняться в бухгалтерской программе.
|
||||
<b>Если у клиента больше 1 действующего допника с услугами PAYG, то данные в отчете могут быть замножены, в этом случае считать вручную</b> --->
|
||||
|
||||
<cfoutput>
|
||||
<form method="post" action="">
|
||||
Период с <input type="text" name="dt_start" value="#dateFormat(dt_start,'YYYY-MM-DD')#"/>
|
||||
по <input type="text" name="dt_finish" value="#dateFormat(dt_finish,'YYYY-MM-DD')#"/>
|
||||
<input type="submit" style="cursor:pointer;"/>
|
||||
<!--- <input type="submit" name="DEBUG" value="DEBUG" style="cursor:pointer;"/> --->
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
<cfflush/>
|
||||
|
||||
<cfmodule template="mod/payg.cfm"
|
||||
dt_finish=#dt_finish#
|
||||
dt_start=#dt_start#
|
||||
tenant_wz_index=#tenant_wz_index#
|
||||
output="report"
|
||||
debug=#isDefined("DEBUG")#
|
||||
/>
|
||||
|
||||
Часов в периоде: <b>#hours#</b> Строк в отчете: <b>#report.qCharge.recordCount#</b><br/>
|
||||
Актуальность данных:
|
||||
VCD Computing: <b>#dateFormat(report.qComputingAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qComputingAge.dt_load,'HH:MM:SS')#</b>
|
||||
VCD Storage: <b>#dateFormat(report.qStorageAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qStorageAge.dt_load,'HH:MM:SS')#</b>
|
||||
S3 хранение: <b>#dateFormat(report.qS3VolAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qS3VolAge.dt_load,'HH:MM:SS')#</b>
|
||||
S3 операции и трафик: <b>#dateFormat(report.qS3OpsTrfAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qS3OpsTrfAge.dt_load,'HH:MM:SS')#</b>
|
||||
|
||||
<br/>
|
||||
<a href="#request.thisPage#?output_xls" title="экспорт в Excel" style="margin-left:.5em; height:100%;" target="_blank"><img src="img/xls.gif" style="vertical-align:text-bottom;"/></a>
|
||||
|
||||
<a href="#request.thisPage#?output_json" title="экспорт в json" style="margin-left:.5em; height:100%;" target="_blank"><img src="img/json.svg" style="vertical-align:text-bottom;" width="13" height="13"/></a>
|
||||
</cfoutput>
|
||||
<table class="worktable">
|
||||
<thead>
|
||||
<td width="1%"></td>
|
||||
<!--- <th width="3%">WZ</th> --->
|
||||
<th width="7%">Артикул</th>
|
||||
<th width="7%">Кол-во (метрика)</th>
|
||||
<th width="3%">Ед.изм.</th>
|
||||
<th width="3%">Цена ₽ со скид., с НДС</th>
|
||||
<th width="3%">Стоимость ₽ с НДС</th>
|
||||
|
||||
<td width="3%"> </td>
|
||||
|
||||
<td width="10%">Услуга</td>
|
||||
<td width="10%">Компонент</td>
|
||||
<!--- <td width="10%">Клиентс. назв.</td> --->
|
||||
|
||||
<td width="3%">GPL с НДС</td>
|
||||
<td width="3%">Скидка%</td>
|
||||
|
||||
<!--- <td width="6%">Дата НОУ</td>
|
||||
<td width="6%">Дата оконч.</td>
|
||||
|
||||
<td width="3%">Ключ строки</td> --->
|
||||
<!--- <td width="3%">Сырая метрика</td> --->
|
||||
<td width="3%">Оплачиваемый объем</td>
|
||||
|
||||
<!--- <td width="5%">Договор</td>
|
||||
<td width="10%">Допник</td>
|
||||
<td width="10%">Сделка</td> --->
|
||||
|
||||
</thead>
|
||||
|
||||
<cfoutput query="report.qCharge" group="svc">
|
||||
<cfset var acc=0/>
|
||||
<tr>
|
||||
<td bgcolor="##ccc"></td>
|
||||
<td bgcolor="##ccc" colspan="5" class="b"> #svc#</td>
|
||||
<td></td>
|
||||
<td bgcolor="##ccc" colspan="99"></td>
|
||||
</tr>
|
||||
<cfoutput>
|
||||
<cfset acc=acc+charge/>
|
||||
<tr>
|
||||
<td>#currentRow#</a></td>
|
||||
|
||||
<td>#code#</td>
|
||||
<td class="r" style="font-size:120%; padding:0 1em;">#chargeable_metric#</td>
|
||||
<td class="c" style="font-size:90%;">#unit#</td>
|
||||
<td class="r">#discounted_price#</td>
|
||||
<td class="r">#charge#</td>
|
||||
|
||||
<td></td>
|
||||
|
||||
<td>#svc#</td>
|
||||
<td>#component#</td>
|
||||
<!--- <td>#user_description#</td> --->
|
||||
|
||||
<td class="r">#price#</td>
|
||||
<td class="r">#discount#</td>
|
||||
|
||||
<td class="r">#metric#</td>
|
||||
|
||||
</tr>
|
||||
</cfoutput>
|
||||
<tr>
|
||||
<td bgcolor="##eee" style="border-bottom:2px solid gray;"></td>
|
||||
<td bgcolor="##eee" colspan="4" class="r" style="border-bottom:2px solid gray;"><b>Итого</b> #svc#:</td>
|
||||
<td bgcolor="##eee" colspan="1" class="r b" style="border-bottom:2px solid gray;">#NumFmt(acc,2)#</td>
|
||||
<td colspan="14" style="border-bottom:2px solid gray;"></td>
|
||||
</tr >
|
||||
</cfoutput>
|
||||
|
||||
</table>
|
||||
<!--- <cfdump var=#qCharge#/> --->
|
||||
|
||||
|
||||
<layout:page section="footer"/>
|
||||
|
||||
<!--- select * from s3billing.billing_per_user_fix_pl('2025-05-01 00:00:00','2025-06-01 00:00:00','1395'); --->
|
||||
|
||||
@@ -4,30 +4,8 @@
|
||||
<cfimport prefix="d" taglib="lib/data"/>
|
||||
<cfimport prefix="layout" taglib="layout"/>
|
||||
</cfsilent>
|
||||
|
||||
<m:prepare_ls entity="payg" accessObject="" pageInfoOut="pageInfo" trackOut="tr"/>
|
||||
|
||||
<cfparam name="dt_finish" type="date" default=#createDateTime(year(Now()),month(Now()),1,0,0,0)#/>
|
||||
<cfparam name="dt_start" type="date" default=#dateAdd('m',-1,dt_finish)#/>
|
||||
<cfset hours=dateDiff('h',dt_start,dt_finish)/>
|
||||
<cfset tenant_wz_index=val(mid(request.auth.wz,3,5))/><!--- cut off WZ --->
|
||||
|
||||
|
||||
<cfif isDefined("output_xls")><cfmodule template="mod/payg.cfm"
|
||||
dt_finish=#dt_finish#
|
||||
dt_start=#dt_start#
|
||||
output="report"
|
||||
debug=#isDefined("DEBUG")#
|
||||
/><layout:xml qRead=#report.qCharge# titleMap=#report.chargeTitleMap# filename="#pageInfo.entity#.xml"/>
|
||||
<cfabort/>
|
||||
</cfif><cfif isDefined("output_json")><cfmodule template="mod/payg.cfm"
|
||||
dt_finish=#dt_finish#
|
||||
dt_start=#dt_start#
|
||||
output="report"
|
||||
debug=#isDefined("DEBUG")#
|
||||
/><!--- <cfdump var=#report#/><cfabort/> ---><layout:json qRead=#report.qCharge# titleMap=#report.chargeTitleMap# filename="#pageInfo.entity#.json"/>
|
||||
<cfabort/>
|
||||
</cfif><!---
|
||||
<!---
|
||||
---><layout:page section="header" pageInfo=#pageInfo#>
|
||||
|
||||
<layout:attribute name="title">
|
||||
@@ -39,117 +17,21 @@
|
||||
</layout:attribute>
|
||||
</layout:page>
|
||||
|
||||
<!--- Внимание! округление вверх при расчете метрик get, put S3. Расчетные суммы могут содержать погрешности округления, поэтому окончательный расчет стоимости (количество * цену) должен выполняться в бухгалтерской программе.
|
||||
<b>Если у клиента больше 1 действующего допника с услугами PAYG, то данные в отчете могут быть замножены, в этом случае считать вручную</b> --->
|
||||
<!--- <script type="text/javascript"/>
|
||||
$(document).ready(function() {
|
||||
document.location="payg.cfm";
|
||||
});
|
||||
</script> --->
|
||||
|
||||
<cfoutput>
|
||||
<form method="post" action="">
|
||||
Период с <input type="text" name="dt_start" value="#dateFormat(dt_start,'YYYY-MM-DD')#"/>
|
||||
по <input type="text" name="dt_finish" value="#dateFormat(dt_finish,'YYYY-MM-DD')#"/>
|
||||
<input type="submit" style="cursor:pointer;"/>
|
||||
<!--- <input type="submit" name="DEBUG" value="DEBUG" style="cursor:pointer;"/> --->
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
<cfflush/>
|
||||
|
||||
<cfmodule template="mod/payg.cfm"
|
||||
dt_finish=#dt_finish#
|
||||
dt_start=#dt_start#
|
||||
output="report"
|
||||
debug=#isDefined("DEBUG")#
|
||||
/>
|
||||
|
||||
Часов в периоде: <b>#hours#</b> Строк в отчете: <b>#report.qCharge.recordCount#</b><br/>
|
||||
Актуальность данных:
|
||||
VCD Computing: <b>#dateFormat(report.qComputingAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qComputingAge.dt_load,'HH:MM:SS')#</b>
|
||||
VCD Storage: <b>#dateFormat(report.qStorageAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qStorageAge.dt_load,'HH:MM:SS')#</b>
|
||||
S3 хранение: <b>#dateFormat(report.qS3VolAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qS3VolAge.dt_load,'HH:MM:SS')#</b>
|
||||
S3 операции и трафик: <b>#dateFormat(report.qS3OpsTrfAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qS3OpsTrfAge.dt_load,'HH:MM:SS')#</b>
|
||||
|
||||
<br/>
|
||||
<a href="#request.thisPage#?output_xls" title="экспорт в Excel" style="margin-left:.5em; height:100%;" target="_blank"><img src="img/xls.gif" style="vertical-align:text-bottom;"/></a>
|
||||
|
||||
<a href="#request.thisPage#?output_json" title="экспорт в json" style="margin-left:.5em; height:100%;" target="_blank"><img src="img/json.svg" style="vertical-align:text-bottom;" width="13" height="13"/></a>
|
||||
</cfoutput>
|
||||
<table class="worktable">
|
||||
<thead>
|
||||
<td width="1%"></td>
|
||||
<!--- <th width="3%">WZ</th> --->
|
||||
<th width="7%">Артикул</th>
|
||||
<th width="7%">Кол-во (метрика)</th>
|
||||
<th width="3%">Ед.изм.</th>
|
||||
<th width="3%">Цена ₽ со скид., с НДС</th>
|
||||
<th width="3%">Стоимость ₽ с НДС</th>
|
||||
|
||||
<td width="3%"> </td>
|
||||
|
||||
<td width="10%">Услуга</td>
|
||||
<td width="10%">Компонент</td>
|
||||
<!--- <td width="10%">Клиентс. назв.</td> --->
|
||||
|
||||
<td width="3%">GPL с НДС</td>
|
||||
<td width="3%">Скидка%</td>
|
||||
|
||||
<!--- <td width="6%">Дата НОУ</td>
|
||||
<td width="6%">Дата оконч.</td>
|
||||
|
||||
<td width="3%">Ключ строки</td> --->
|
||||
<!--- <td width="3%">Сырая метрика</td> --->
|
||||
<td width="3%">Оплачиваемый объем</td>
|
||||
|
||||
<!--- <td width="5%">Договор</td>
|
||||
<td width="10%">Допник</td>
|
||||
<td width="10%">Сделка</td> --->
|
||||
|
||||
</thead>
|
||||
|
||||
<cfoutput query="report.qCharge" group="svc">
|
||||
<cfset var acc=0/>
|
||||
<tr>
|
||||
<td bgcolor="##ccc"></td>
|
||||
<td bgcolor="##ccc" colspan="5" class="b"> #svc#</td>
|
||||
<td></td>
|
||||
<td bgcolor="##ccc" colspan="99"></td>
|
||||
</tr>
|
||||
<cfoutput>
|
||||
<cfset acc=acc+charge/>
|
||||
<tr>
|
||||
<td>#currentRow#</a></td>
|
||||
|
||||
<td>#code#</td>
|
||||
<td class="r" style="font-size:120%; padding:0 1em;">#chargeable_metric#</td>
|
||||
<td class="c" style="font-size:90%;">#unit#</td>
|
||||
<td class="r">#discounted_price#</td>
|
||||
<td class="r">#charge#</td>
|
||||
|
||||
<td></td>
|
||||
|
||||
<td>#svc#</td>
|
||||
<td>#component#</td>
|
||||
<!--- <td>#user_description#</td> --->
|
||||
|
||||
<td class="r">#price#</td>
|
||||
<td class="r">#discount#</td>
|
||||
|
||||
<td class="r">#metric#</td>
|
||||
|
||||
</tr>
|
||||
</cfoutput>
|
||||
<tr>
|
||||
<td bgcolor="##eee" style="border-bottom:2px solid gray;"></td>
|
||||
<td bgcolor="##eee" colspan="4" class="r" style="border-bottom:2px solid gray;"><b>Итого</b> #svc#:</td>
|
||||
<td bgcolor="##eee" colspan="1" class="r b" style="border-bottom:2px solid gray;">#NumFmt(acc,2)#</td>
|
||||
<td colspan="14" style="border-bottom:2px solid gray;"></td>
|
||||
</tr >
|
||||
</cfoutput>
|
||||
|
||||
</table>
|
||||
<!--- <cfdump var=#qCharge#/> --->
|
||||
<h1>
|
||||
Подождите пожалуйста, формирование отчета может занять некоторое время
|
||||
</h1>
|
||||
<a href="payg.cfm">Если автоматического перенаправления не произошло, перейдите по ссылке</a>
|
||||
|
||||
|
||||
<layout:page section="footer"/>
|
||||
|
||||
<cflocation url="payg.cfm" addToken="No"/>
|
||||
|
||||
<!--- select * from s3billing.billing_per_user_fix_pl('2025-05-01 00:00:00','2025-06-01 00:00:00','1395'); --->
|
||||
|
||||
|
||||
@@ -1,78 +1,142 @@
|
||||
<cfset msStartAt=getTickCount()/>
|
||||
<cfparam name="dt_finish" type="date" default=#createDateTime(year(Now()),month(Now()),1,0,0,0)#/>
|
||||
<cfparam name="dt_start" type="date" default=#dateAdd('m',-1,dt_finish)#/>
|
||||
<cfset hours=dateDiff('h',dt_start,dt_finish)/>
|
||||
<cfparam name="dt_finish" type="date" default=#dateAdd('d',-1,createDateTime(year(Now()),month(Now()),1,0,0,0))#/>
|
||||
<cfparam name="dt_start" type="date" default=#dateAdd('m',-1,createDateTime(year(Now()),month(Now()),1,0,0,0))#/>
|
||||
<cfset hours=dateDiff('h', dt_start, dateAdd('d', 1, dt_finish))/>
|
||||
<cfset tenant_wz_index=val(mid(request.auth.wz,3,5))/><!--- cut off WZ --->
|
||||
|
||||
<cffunction name="snake2camel"
|
||||
|
||||
<cfscript>
|
||||
function gaussianRound(numeric number, numeric precision = 0) {
|
||||
var factor = 10 ^ precision;
|
||||
var scaledNumber = number * factor;
|
||||
var absScaled = abs(scaledNumber);
|
||||
var sign = sgn(scaledNumber);
|
||||
var floored = int(absScaled);
|
||||
|
||||
// If it's not ending in exactly .5, use standard rounding or precision scaling
|
||||
if (absScaled - floored != 0.5) {
|
||||
return round(number * factor) / factor;
|
||||
}
|
||||
|
||||
// If it is exactly .5, round towards the nearest even number
|
||||
if (floored % 2 != 0) {
|
||||
// Nearest even is UP
|
||||
return (floored + 1) * sign / factor;
|
||||
} else {
|
||||
// Nearest even is DOWN
|
||||
return floored * sign / factor;
|
||||
}
|
||||
}
|
||||
</cfscript>
|
||||
|
||||
<cffunction name="iso8601dtFormat"
|
||||
returntype="string"
|
||||
output="false"
|
||||
hint="convert snake style name to camel style name">
|
||||
<cfargument name="snake" type="string" required="true" />
|
||||
<cfreturn #reReplace(ARGUMENTS.snake,"_([a-z])","\u\1","ALL")#/>
|
||||
</cffunction>
|
||||
|
||||
<cffunction name="camel2snake"
|
||||
returntype="string"
|
||||
output="false"
|
||||
hint="convert camel style name to snake style name">
|
||||
<cfargument name="camel" type="string" required="true" />
|
||||
<cfreturn #reReplace(ARGUMENTS.camel,"([A-Z])","_\l\1","ALL")#/>
|
||||
</cffunction>
|
||||
|
||||
<cffunction name="query2json"
|
||||
output="false"
|
||||
hint="print query in json format as array of structures">
|
||||
<cfargument name="qry" type="query" required="true"/><!--- column names should not contain commas --->
|
||||
<cfargument name="convertSnakeToCamel" type="boolean" default=true/>
|
||||
|
||||
<cfset var columnsIn=#arguments.qry.columnList()#/>
|
||||
<cfset var columnsOut=""/>
|
||||
|
||||
<cfif arguments.convertSnakeToCamel>
|
||||
<cfloop list=#columnsIn# item="col">
|
||||
<cfset columnsOut=listAppend(columnsOut,snake2camel(col))/>
|
||||
</cfloop>
|
||||
|
||||
<cfset var outArray=arrayNew(1)/>
|
||||
//copy fields to structure, renaming fields, this preserves data type
|
||||
<cfloop query=#arguments.qry#>
|
||||
<cfset var structRow=structNew()/>
|
||||
<cfloop index="i" from="1" to=#listLen(columnsOut)#>
|
||||
<cfset structInsert(structRow,"#listGetAt(#columnsOut#,i)#",arguments.qry["#listGetAt(#columnsIn#,i)#"])/>
|
||||
</cfloop>
|
||||
<cfset arrayAppend(outArray,structRow)/>
|
||||
</cfloop>
|
||||
|
||||
<cfreturn serializeJSON(outArray)/>
|
||||
<cfelse>
|
||||
<cfreturn serializeJSON(arguments.qry,"struct")/>
|
||||
</cfif>
|
||||
hint="formates date and time like this: 2023-12-18T15:41:42.516+0300">
|
||||
<cfargument name="input" required="true" />
|
||||
<cfreturn "#dateFormat( input, "yyyy-mm-dd" )#T#timeFormat( input, "HH:mm:ss.lXX" )#"/>
|
||||
</cffunction>
|
||||
|
||||
|
||||
<cfmodule template="mod/payg.cfm"
|
||||
<cfmodule template="mod/compute_payg.cfm"
|
||||
dt_finish=#dt_finish#
|
||||
dt_start=#dt_start#
|
||||
tenant_wz_index=#tenant_wz_index#
|
||||
output="report"
|
||||
debug=#isDefined("DEBUG")#
|
||||
/>
|
||||
<cfset out={
|
||||
"hours"=#hours#,
|
||||
"vcdComputingLoadedAt"="#dateFormat(report.qComputingAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qComputingAge.dt_load,'HH:MM:SS')#",
|
||||
"vcdStorageLoadedAt"="#dateFormat(report.qStorageAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qStorageAge.dt_load,'HH:MM:SS')#",
|
||||
"s3StorageLoadedAt"="#dateFormat(report.qComputingAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qS3VolAge.dt_load,'HH:MM:SS')#",
|
||||
"s3OpsTrfLoadedAt"="#dateFormat(report.qS3OpsTrfAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qS3OpsTrfAge.dt_load,'HH:MM:SS')#",
|
||||
"records"=#report.qCharge.recordCount#,
|
||||
"queryDurationMs"=#(getTickCount() - msStartAt)#,
|
||||
"report"=#report.qCharge.reduce((result, row) => {
|
||||
result.append(row);
|
||||
return result;
|
||||
}, [])#
|
||||
}/>
|
||||
<!--- "dtStart"="#dateFormat(dt_start, "yyyy-mm-dd")#"
|
||||
,"dtFinish"="#dateFormat(dt_finish, "yyyy-mm-dd")#" --->
|
||||
<cfset temp.out=[
|
||||
"dtStart="=#iso8601dtFormat(dt_start)#
|
||||
,"dtFinish"=#iso8601dtFormat(dt_finish)#
|
||||
,"hours"=#hours#
|
||||
,"tenantWzIndex"="#tenant_wz_index#"
|
||||
,"wz"=#request.auth.wz#
|
||||
,"login"=#request.auth.login#
|
||||
,"appVersion"=#request.APP_VERSION#
|
||||
,"vcdComputingLoadedAt"="#iso8601dtFormat(report.qComputingAge.dt_load)#"
|
||||
,"vcdStorageLoadedAt"="#iso8601dtFormat(report.qStorageAge.dt_load)#"
|
||||
,"s3StorageLoadedAt"="#iso8601dtFormat(report.qComputingAge.dt_load)#"
|
||||
,"s3OpsTrfLoadedAt"="#iso8601dtFormat(report.qS3OpsTrfAge.dt_load)#"
|
||||
,"records"=#report.qCharge.recordCount#
|
||||
,"queryDurationMs"=#(getTickCount() - msStartAt)#
|
||||
,"periods"=[]
|
||||
]/><!--- using [] instead of {} for struct literals to obtain linked (ordered) structures: keys order preserved --->
|
||||
<!--- beware nulls --->
|
||||
<cfoutput query="report.qCharge" group="year">
|
||||
<cfoutput group="month">
|
||||
<cfset temp.period=[
|
||||
"year"=#year#
|
||||
,"month"=#month#
|
||||
,"services"=[]
|
||||
]/>
|
||||
<cfset arrayAppend(temp.out.periods,temp.period)/>
|
||||
|
||||
<cfoutput group="svc">
|
||||
<cfset var accum_cost_svc = 0/>
|
||||
<!--- <cfset var accum_metric_component = 0/> --->
|
||||
|
||||
<cfset "temp.service"=["svc"="#svc#"
|
||||
,"serviceCode"="#service_code#"
|
||||
,"serviceCustomName"="#serviceCustomName#"
|
||||
<!--- ,"note"="#(serviceHash EQ '')?'не найдено в договоре':''#" --->
|
||||
,"hash"="#serviceHash#"
|
||||
<!--- ,"metric"=#accum_metric_component# --->
|
||||
,"components"=[]
|
||||
]/>
|
||||
|
||||
<cfoutput group="code">
|
||||
<cfoutput group="serviceStart">
|
||||
<!--- <cfset accum_metric_component += isNumeric(metric) ? metric : 0/> --->
|
||||
<cfset accum_metric_dimension_1 = 0/>
|
||||
|
||||
<cfset "temp.component"=["code"="#code#"
|
||||
,"codeMetered"="#m_code#"
|
||||
,"component"="#component#"
|
||||
,"unit"="#unit#"
|
||||
,"freeTier"="#free_tier#"
|
||||
,"price"="#gaussianRound(discounted_price,2)#"
|
||||
,"details"=[]
|
||||
]/>
|
||||
|
||||
<cfoutput group="dimension_1">
|
||||
<cfset accum_metric_dimension_1 += isNumeric(metric) ? metric : 0/>
|
||||
|
||||
<cfset temp.dimension=["dimension1name"="#dimension_1_name#"
|
||||
,"dimension1value"="#dimension_1#"
|
||||
,"dtBilledFrom"="#dateFormat(dt_billed_from,'YYYY-MM-DD')#"
|
||||
,"dtBilledTo"="#dateFormat(dt_billed_to,'YYYY-MM-DD')#"
|
||||
,"metric"=#(metric NEQ 0 AND isNumeric(metric))?round(metric,3):javaCast("null",0)#
|
||||
,"unit"="#unit#"
|
||||
<!--- ,"price"="#gaussianRound(discounted_price,2)#" --->
|
||||
]/>
|
||||
|
||||
<cfset arrayAppend(temp.component.details, temp.dimension)/>
|
||||
</cfoutput><!--- dimension_1 --->
|
||||
|
||||
<!--- считаем, что free_tier NOT NULL (вместо NULL 0) --->
|
||||
<cfset var payable_metric_dimension_1 = (isNumeric(accum_metric_dimension_1))? max(ceiling(accum_metric_dimension_1) - free_tier, 0):javaCast("null",0)/>
|
||||
<cfset var cost_dimension_1 = precisionEvaluate("gaussianRound(payable_metric_dimension_1*gaussianRound(discounted_price, 2), 2)")/>
|
||||
<cfset accum_cost_svc = precisionEvaluate("accum_cost_svc + cost_dimension_1")/>
|
||||
|
||||
<cfset "temp.component.metric"=#(accum_metric_dimension_1 NEQ 0 AND isNumeric(accum_metric_dimension_1))? round(accum_metric_dimension_1,3):javaCast("null",0)#/>
|
||||
<cfset "temp.component.metricPayable"=#payable_metric_dimension_1#/>
|
||||
<cfset "temp.component.cost"=#cost_dimension_1#/>
|
||||
|
||||
<cfset arrayAppend(temp.service.components, temp.component)/>
|
||||
</cfoutput><!--- serviceStart (component version in specification, that is svc version joined down to the component) --->
|
||||
|
||||
<cfset "temp.service.cost"=#accum_cost_svc#/>
|
||||
</cfoutput><!--- code (component) --->
|
||||
|
||||
<cfset arrayAppend(temp.period.services, temp.service)/>
|
||||
</cfoutput><!--- svc --->
|
||||
</cfoutput><!--- month --->
|
||||
</cfoutput><!--- year --->
|
||||
<cfset "temp.out.durationMs"=(getTickCount()-request.startTickCount)/>
|
||||
<cfcontent
|
||||
type="application/json"
|
||||
/><cfoutput>#serializeJSON(out)#</cfoutput>
|
||||
/><cfoutput>#serializeJSON(temp.out)#</cfoutput>
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,566 @@
|
||||
<cfimport prefix="m" taglib="../lib"/>
|
||||
<cfimport prefix="d" taglib="../lib/data"/>
|
||||
|
||||
<cfparam name="ATTRIBUTES.dt_finish" type="date" default=#createDateTime(year(Now()),month(Now()),1,0,0,0)#/>
|
||||
<cfparam name="ATTRIBUTES.dt_start" type="date" default=#dateAdd('m',-1,ATTRIBUTES.dt_finish)#/>
|
||||
<cfparam name="ATTRIBUTES.output" type="string" default="report"/>
|
||||
<cfparam name="ATTRIBUTES.debug" type="boolean" default=false/>
|
||||
<cfparam name="ATTRIBUTES.tenant_wz_index" type="string"/>
|
||||
<cfparam name="ATTRIBUTES.restrict_to_own_instances" type="boolean" default=true/>
|
||||
|
||||
|
||||
|
||||
<cfset hours=dateDiff('h', ATTRIBUTES.dt_start, dateAdd("d",1,ATTRIBUTES.dt_finish))/> <!--- *** нужно для каждого фрагмента --->
|
||||
<cfif hours LE 0>
|
||||
<cfthrow message="Некорректный период" detail="Период должен быть больше 0"/>
|
||||
</cfif>
|
||||
<!---
|
||||
*** ВНИМАНИЕ! Вычитать минимальный бесплатный лимит (free tier) нужно после агрегации!
|
||||
Исходная последовательность расчетов сначала делает агрегацию по месяцу, при расчете по дням нужно менять порядок
|
||||
--->
|
||||
<!---
|
||||
Скрытое противоречие, которое требует разрешения: если у нас несколько периодов тарификации в одном месяце (по разной цене), ИЗ КАКОГО вычитать минимальный лимит?
|
||||
Еще сложность, если лимита хватает на несколько периодов тарификации, как его распределять по периодам. Если тарификация строго по месяцам, этой проблемы нет.
|
||||
Это можно сделать процедурно, но сложность расчета все возрастает
|
||||
--->
|
||||
<!--- *** Проверить, что у нас не биллится закрытый период (закрытый следующим) - возможно, с учетом line_key
|
||||
- насколько вижу, прошлый период закрывается, причем концы отрезки закрытые (конец включается). Считаем, что этой проблемы нет
|
||||
--->
|
||||
<!--- QoQ does not support join syntax, and of course outer joins, at least of Lucee 5.4--->
|
||||
<!--- а внешние джойны хорошо подсвечивают ошибки в данных, особенно помогает full --->
|
||||
|
||||
<cfmodule template="crm_contract.cfm" wz="WZ#numberFormat(ATTRIBUTES.tenant_wz_index,'00000')#" out="qSpecification"/>
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
qSpecification (from CRM)
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qSpecification#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<cfquery name="qComputingAge">
|
||||
select max(capacity_resource.timestamp) as dt_load from ngcloud_ru.capacity_resource
|
||||
</cfquery>
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qComputingAge#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<cfquery name="qStorageAge" datasource="rpt">
|
||||
select max(capacity_storage.timestamp) as dt_load from ngcloud_ru.capacity_storage
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qStorageAge#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<cfquery name="qS3VolAge">
|
||||
select max(timestamp_addition) as dt_load from s3billing.bucket_stat
|
||||
</cfquery>
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qS3VolAge#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<cfquery name="qS3OpsTrfAge">
|
||||
select max(time) as dt_load from s3billing.usage_bucket_by_user
|
||||
</cfquery>
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qS3OpsTrfAge#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
|
||||
<cfset qFreeTier=queryNew("code,free_tier","CF_SQL_VARCHAR,CF_SQL_NUMERIC",[['paas.s3.ceph.vol-m',1],['paas.s3.ceph.get-m',10],['paas.s3.ceph.put-m',1],['paas.s3.ceph.trf-m',100]])/>
|
||||
<!--- -- все-таки пришлось прибить гвоздями - в каталоге нет даже бесплатного лимита, не то что скидочной политики
|
||||
-- придется добавить в каталог
|
||||
-- бесплатный лимит есть только для S3 HOT (в месяц в единицах измерения) --->
|
||||
|
||||
|
||||
<!--- ******************************** здесь нужно организовать пересечение версионной спецификации с анализируемым диапазоном дат --->
|
||||
<!--- Проверка: включаем дату смены цены в диапазон и смотрим --->
|
||||
<!--- Важно: если в периоде было 2+ цены, то строки должны быть замножены, а цена за период перестает иметь смысл (не показывать же среднее арифметическое, это неправильно) --->
|
||||
<!--- Left Outer Join with Free Tier --->
|
||||
<cfquery name="qSpec" dbtype="query">
|
||||
select s.catalogName as svc, s.component, s.serviceCode as service_code, s.fullCode as code, s.measureShort as unit
|
||||
, s.priceWVat as price, (s.discount + s.serviceDiscount - s.discount*s.serviceDiscount/100) as discount
|
||||
,s.serviceStart, s.serviceEnd, s.serviceHash, s.serviceCustomName, f.free_tier
|
||||
from qSpecification s, qFreeTier f
|
||||
WHERE s.fullCode=f.code
|
||||
AND s.serviceType = 3
|
||||
|
||||
UNION
|
||||
|
||||
select s.catalogName as svc, s.component, s.serviceCode as service_code, s.fullCode as code, s.measureShort as unit
|
||||
, s.priceWVat as price, (s.discount + s.serviceDiscount - s.discount*s.serviceDiscount/100) as discount
|
||||
,s.serviceStart, s.serviceEnd, s.serviceHash, s.serviceCustomName, 0
|
||||
from qSpecification s
|
||||
WHERE s.fullCode NOT IN (<cfqueryparam value="#ValueList(qFreeTier.code)#" cfsqltype="cf_sql_varchar" list="true">)
|
||||
AND s.serviceType = 3
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
qSpec (Left Outer Join with Free Tier)
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qSpec#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
|
||||
<!--- -- 1. Create a specialized expression index matching your date filters
|
||||
CREATE INDEX idx_capacity_storage_perf_test ON ngcloud_ru.capacity_storage (
|
||||
vdc_id,
|
||||
(timestamp::date),
|
||||
storage_profile_types_id
|
||||
)
|
||||
INCLUDE (limit, used);
|
||||
|
||||
-- 2. Optional: Standardize tenant scanning since it currently falls back to Seq Scan
|
||||
CREATE INDEX idx_tenant_wzcode ON ngcloud_ru.tenant (wzcode); --->
|
||||
|
||||
<!--- *** Нужно еще реализовать в модели данных (каталоге) политики бесплатного минимума (free tier), сейчас прибито гвоздями --->
|
||||
<cfquery name="qComputing">
|
||||
select 'WZ'||to_char(tenant.wzcode,'FM00000') as wz, vdc.name as vdc_name,
|
||||
case
|
||||
WHEN vdc.name LIKE '%-v1cl1%' THEN 'iaas.ngc.i29'
|
||||
WHEN vdc.name LIKE '%-v1cl2%' THEN 'iaas.ngc.i31'
|
||||
WHEN vdc.name LIKE '%-v1cl4%' THEN 'iaas.ngc.a28'
|
||||
WHEN vdc.name LIKE '%-v1cl5%' THEN 'iaas.ngc.a45'
|
||||
WHEN vdc.name LIKE '%-v1cl6%' THEN 'iaas.ngc.i28'
|
||||
WHEN vdc.name LIKE '%-v1cl7%' THEN 'iaas.ngc.a40' -- *** смапить все кластера
|
||||
ELSE '['||vdc.name||']' end as code,
|
||||
sum(cpu_used/cpu_speed)/4. as core_h,
|
||||
sum(mem_used)/1024/4. as gb_h,
|
||||
capacity_resource.timestamp::date as dt,
|
||||
vdc.name as dimension_1,
|
||||
null as dimension_2
|
||||
from ngcloud_ru.capacity_resource
|
||||
join ngcloud_ru.vdc on capacity_resource.vdc_id=vdc.id
|
||||
join ngcloud_ru.tenant on tenant.id=vdc.tenant_id
|
||||
where tenant.wzcode = <cfqueryparam cfsqltype="cf_sql_integer" value=#ATTRIBUTES.tenant_wz_index#/>
|
||||
AND capacity_resource.timestamp >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#attributes.dt_start#/>
|
||||
AND capacity_resource.timestamp < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dateAdd("d",1,attributes.dt_finish)#/>
|
||||
group by tenant.wzcode, vdc.name, capacity_resource.timestamp::date
|
||||
order by tenant.wzcode, vdc.name, capacity_resource.timestamp::date;
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
qComputing
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qComputing#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<!--- если захочется сгенерить литерал таблицы соответствия
|
||||
with a as (
|
||||
select * from ngcloud_ru.storage_profile_types
|
||||
)
|
||||
select '('||id||', '''|| name||''', '''||
|
||||
|
||||
case
|
||||
when name ilike '%fastssd%' then 'fstssd'
|
||||
when name ilike '%ssd%' then 'ssd'
|
||||
when name ilike '%sata%' then 'sata'
|
||||
else '' end
|
||||
||''''||')'
|
||||
from a
|
||||
--->
|
||||
<!--- переделать storage_profile_types с расшифровкой ssd, sata, можно прямо до каталожного кода --->
|
||||
<!--- очень долго исполняется --->
|
||||
<cfquery name="qStorage">
|
||||
select 'WZ'||to_char(tenant.wzcode,'FM00000') as wz, vdc.name as vdc_name,
|
||||
case
|
||||
WHEN vdc.name LIKE '%-v1cl1%' THEN 'iaas.ngc.i29'
|
||||
WHEN vdc.name LIKE '%-v1cl2%' THEN 'iaas.ngc.i31'
|
||||
WHEN vdc.name LIKE '%-v1cl4%' THEN 'iaas.ngc.a28'
|
||||
WHEN vdc.name LIKE '%-v1cl5%' THEN 'iaas.ngc.a45'
|
||||
WHEN vdc.name LIKE '%-v1cl6%' THEN 'iaas.ngc.i28'
|
||||
WHEN vdc.name LIKE '%-v1cl7%' THEN 'iaas.ngc.a40'
|
||||
ELSE '['||vdc.name||']' END
|
||||
|| CASE
|
||||
WHEN storage_profile_types.name ILIKE '%FASTSSD%' THEN '.fstssd-m'
|
||||
WHEN storage_profile_types.name ILIKE '%SSD%' THEN '.ssd-m'
|
||||
WHEN storage_profile_types.name ILIKE '%SAS%' THEN '.sas-m'
|
||||
WHEN storage_profile_types.name ILIKE '%SATA%' THEN '.sata-m'
|
||||
ELSE '.['|| storage_profile_types.name ||']' END
|
||||
as code,
|
||||
storage_profile_types.name, -- *** это не тип, а профайл
|
||||
sum("limit")/1024./4./720 as gb_m_limit,
|
||||
sum(used)/1024./4./720 as gb_m_used,
|
||||
capacity_storage.timestamp::date as dt,
|
||||
vdc.name as dimension_1,
|
||||
storage_profile_types.name as dimension_2
|
||||
from ngcloud_ru.capacity_storage
|
||||
join ngcloud_ru.vdc on capacity_storage.vdc_id=vdc.id
|
||||
join ngcloud_ru.tenant on tenant.id=vdc.tenant_id
|
||||
join ngcloud_ru.storage_profile_types on capacity_storage.storage_profile_types_id=storage_profile_types.id
|
||||
where tenant.wzcode = <cfqueryparam cfsqltype="cf_sql_integer" value=#ATTRIBUTES.tenant_wz_index#/> --AND 1=0
|
||||
AND capacity_storage.timestamp >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#attributes.dt_start#/>
|
||||
AND capacity_storage.timestamp < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dateAdd("d",1,attributes.dt_finish)#/>
|
||||
group by tenant.wzcode, vdc.name, storage_profile_types.name, capacity_storage.timestamp::date
|
||||
order by tenant.wzcode, vdc.name, storage_profile_types.name, capacity_storage.timestamp::date
|
||||
;
|
||||
</cfquery>
|
||||
<!--- create index IX_capacity_storage_sort on ngcloud_ru.capacity_storage(vdc_id,storage_profile_types_id,timestamp); --->
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
qStorage
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qStorage#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<!---
|
||||
"placement" "size_gb" "get_10k" "put_10k" "bytes_sent_gb"
|
||||
HOT_FREE_LIMIT 1 10 1 100
|
||||
--->
|
||||
<!--- надо дисконтировать не ГБ-часы а ГБ-месяцы --->
|
||||
<cfquery name="qS3Vol">
|
||||
select /* *** ниже дублирование кода агрегации - round ceil etc, обратить внимание при правке */
|
||||
/* *** переделать на avg - сначала агрегировать по бакетам*/
|
||||
(sum(bucket_stat.usage_rgw_main_size_actual)/720) as vol_B
|
||||
,ceil(sum(bucket_stat.usage_rgw_main_size_actual)/720/1024/1024/1024) as vol_GB
|
||||
<!--- ,greatest(ceil(sum(bucket_stat.usage_rgw_main_size_actual)/<cfqueryparam cfsqltype="cf_sql_integer" value=#hours#/>
|
||||
/1024/1024/1024)-
|
||||
case when bucket_stat.placement_id = 1 then 1 else 0 end, 0) as vol_GB_free_tier_subtracted /*считается не в точности так, как в функции*/ --->
|
||||
,case
|
||||
when bucket_stat.placement_id = 1 then 'paas.s3.ceph'
|
||||
when bucket_stat.placement_id = 2 then 'paas.s3.cphc'
|
||||
else '['|| TO_CHAR(bucket_stat.placement_id,'FM9') ||']' end as code
|
||||
--,bucket_stat.placement_id
|
||||
,'WZ'||lpad(bucket_stat.owner, 5, '0') as wz -- *** здесь не число, а строка, поэтому другая формула обратной сборки WZ
|
||||
,bucket_stat.timestamp_addition::date as dt
|
||||
,bucket_info.name || ' - ' || case
|
||||
when bucket_stat.placement_id = 1 then 'paas.s3.ceph'
|
||||
when bucket_stat.placement_id = 2 then 'paas.s3.cphc'
|
||||
else '['|| TO_CHAR(bucket_stat.placement_id,'FM9') ||']' end
|
||||
as dimension_1
|
||||
,null as dimension_2
|
||||
from s3billing.bucket_stat
|
||||
join s3billing.placement ON s3billing.placement.id=bucket_stat.placement_id
|
||||
join s3billing.bucket_info ON bucket_info.id=bucket_stat.bucket_id
|
||||
where bucket_stat.placement_id in (1,2)
|
||||
AND bucket_stat.owner = <cfqueryparam cfsqltype="cf_sql_varchar" value=#ATTRIBUTES.tenant_wz_index#/>
|
||||
AND bucket_stat.timestamp_addition >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#attributes.dt_start#/>
|
||||
AND bucket_stat.timestamp_addition < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dateAdd("d",1,attributes.dt_finish)#/>
|
||||
group by bucket_stat.owner, bucket_stat.placement_id, bucket_info.name, bucket_stat.timestamp_addition::date
|
||||
order by bucket_stat.owner, bucket_stat.placement_id, bucket_info.name, bucket_stat.timestamp_addition::date;
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
qS3Vol
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qS3Vol#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
|
||||
<cfquery name="qS3OpsTrf">
|
||||
select
|
||||
sum(
|
||||
CASE WHEN
|
||||
(category.name LIKE 'get%'
|
||||
OR category.name LIKE 'head%'
|
||||
OR category.name LIKE 'options%'
|
||||
) THEN ops ELSE 0 END
|
||||
) as get
|
||||
,ceil(sum(
|
||||
CASE WHEN
|
||||
(category.name LIKE 'get%'
|
||||
OR category.name LIKE 'head%'
|
||||
OR category.name LIKE 'options%'
|
||||
) THEN ops ELSE 0 END
|
||||
)/10000) as get_10k
|
||||
/*,greatest(ceil(sum(
|
||||
CASE WHEN
|
||||
(category.name LIKE 'get%'
|
||||
OR category.name LIKE 'head%'
|
||||
OR category.name LIKE 'options%'
|
||||
) THEN ops ELSE 0 END
|
||||
)/10000) - CASE WHEN bucket_info.placement_id = 1 THEN 10 ELSE 0 END, 0
|
||||
) as get_10k_free_tier_subtracted*/
|
||||
|
||||
,sum(
|
||||
CASE WHEN
|
||||
(category.name LIKE 'put%'
|
||||
OR category.name LIKE 'post%'
|
||||
OR category.name LIKE 'patch%'
|
||||
OR category.name LIKE 'list%'
|
||||
) THEN ops ELSE 0 END
|
||||
) as put
|
||||
,ceil(sum(
|
||||
CASE WHEN
|
||||
(category.name LIKE 'put%'
|
||||
OR category.name LIKE 'post%'
|
||||
OR category.name LIKE 'patch%'
|
||||
OR category.name LIKE 'list%'
|
||||
) THEN ops ELSE 0 END
|
||||
)/10000) as put_10k
|
||||
/*,greatest(ceil(sum(
|
||||
CASE WHEN
|
||||
(category.name LIKE 'put%'
|
||||
OR category.name LIKE 'post%'
|
||||
OR category.name LIKE 'patch%'
|
||||
OR category.name LIKE 'list%'
|
||||
) THEN ops ELSE 0 END
|
||||
)/10000) - CASE WHEN bucket_info.placement_id = 1 THEN 1 ELSE 0 END, 0
|
||||
) as put_10k_free_tier_subtracted*/
|
||||
|
||||
,(sum(bytes_sent)) as bytes_sent
|
||||
,ceil(sum(bytes_sent)/1024/1024/1024) as bytes_sent_GB
|
||||
/*,greatest(ceil(sum(bytes_sent)/1024/1024/1024) - CASE WHEN bucket_info.placement_id = 1 THEN 100 ELSE 0 END, 0
|
||||
) as bytes_sent_GB_free_tier_subtracted */
|
||||
,case
|
||||
when bucket_info.placement_id = 1 then 'paas.s3.ceph'
|
||||
when bucket_info.placement_id = 2 then 'paas.s3.cphc'
|
||||
else '['|| TO_CHAR(bucket_info.placement_id,'FM9') ||']' end as code --*** зачем делать там ключ bigint
|
||||
,bucket_info.placement_id
|
||||
--category.name, bucket_info.name
|
||||
,'WZ'||lpad(user_info.name, 5, '0') as wz
|
||||
,usage_bucket_by_user.time::date as dt
|
||||
,bucket_info.name || ' - ' || case
|
||||
when bucket_info.placement_id = 1 then 'paas.s3.ceph'
|
||||
when bucket_info.placement_id = 2 then 'paas.s3.cphc'
|
||||
else '['|| TO_CHAR(bucket_info.placement_id,'FM9') ||']' end
|
||||
as dimension_1
|
||||
,null as dimension_2
|
||||
from s3billing.usage_bucket_by_user
|
||||
join s3billing.user_info on usage_bucket_by_user.user_id=user_info.id
|
||||
join s3billing.category on usage_bucket_by_user.category_id=category.id
|
||||
join s3billing.bucket_info on usage_bucket_by_user.bucketid=bucket_info.id
|
||||
join s3billing.placement on bucket_info.placement_id=placement.id
|
||||
where 1=1
|
||||
AND user_info.name = <cfqueryparam cfsqltype="cf_sql_varchar" value=#ATTRIBUTES.tenant_wz_index#/>
|
||||
AND usage_bucket_by_user.time >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#attributes.dt_start#/>
|
||||
AND usage_bucket_by_user.time < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#dateAdd("d",1,attributes.dt_finish)#/>
|
||||
group by user_info.name, bucket_info.placement_id, bucket_info.name, usage_bucket_by_user.time::date
|
||||
order by user_info.name, bucket_info.placement_id, bucket_info.name, usage_bucket_by_user.time::date;
|
||||
</cfquery>
|
||||
|
||||
<!--- здесь метрики уже сгруппированы по дням. Умножать на цену еще рано, надо сильно позже --->
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
qS3OpsTrf
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qS3OpsTrf#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<!--- собрали все метрики в один резалтсет --->
|
||||
<!--- Здесь мы знаем единицы измерения, причем надежнее, чем в спецификации --->
|
||||
<cfquery name="qUnifiedMetric" dbType="query">
|
||||
select dt, wz, code + '.vcpu-m' as code, core_h as raw_metric, core_h as metric,
|
||||
dimension_1, 'vdc' as dimension_1_name, dimension_2, NULL as dimension_2_name, 'ядро-ч' as unit
|
||||
from qComputing
|
||||
|
||||
union all
|
||||
select dt, wz, code + '.ram-m' as code, gb_h as raw_metric, gb_h as metric,
|
||||
dimension_1, 'vdc' as dimension_1_name, dimension_2, NULL as dimension_2_name, 'ГБайт-ч' as unit
|
||||
from qComputing
|
||||
|
||||
union all
|
||||
select dt, wz, code, gb_m_used as raw_metric, gb_m_used as metric,
|
||||
dimension_1, 'vdc' as dimension_1_name, dimension_2, 'storage policy' as dimension_2_name, 'ГБайт-м' as unit
|
||||
from qStorage
|
||||
|
||||
union all
|
||||
select dt, wz, code + '.vol-m', vol_b as raw_metric, vol_gb as metric,
|
||||
dimension_1, 'bucket' as dimension_1_name, dimension_2, NULL as dimension_2_name, 'ГБайт-м' as unit
|
||||
from qS3Vol
|
||||
|
||||
union all
|
||||
select dt, wz, code + '.get-m', get as raw_metric, get_10k as metric,
|
||||
dimension_1, 'bucket' as dimension_1_name, dimension_2, NULL as dimension_2_name, '10тыс.шт.' as unit
|
||||
from qS3OpsTrf
|
||||
|
||||
union all
|
||||
select dt, wz, code + '.put-m', put as raw_metric, put_10k as metric,
|
||||
dimension_1, 'bucket' as dimension_1_name, dimension_2, NULL as dimension_2_name, '10тыс.шт.' as unit
|
||||
from qS3OpsTrf
|
||||
|
||||
union all
|
||||
select dt, wz, code + '.trf-m', bytes_sent as raw_metric, bytes_sent_gb as metric,
|
||||
dimension_1, 'bucket' as dimension_1_name, dimension_2, NULL as dimension_2_name, 'ГБайт' as unit
|
||||
from qS3OpsTrf
|
||||
|
||||
order by dt, code, dimension_1, dimension_2 <!--- /*dimension_*_name нужно только в качестве заголовка *** потом оптимизировать */ --->
|
||||
</cfquery>
|
||||
<!--- clean extra spaces to work around QoQ bug --->
|
||||
<cfloop query="qUnifiedMetric">
|
||||
<cfset qUnifiedMetric.dimension_1_name=trim(qUnifiedMetric.dimension_1_name)/>
|
||||
<cfset qUnifiedMetric.dimension_2_name=trim(qUnifiedMetric.dimension_2_name)/>
|
||||
<!--- *** возможно, и с другими полями придется сделать то же самое --->
|
||||
</cfloop>
|
||||
<!--- This is a known, long-standing quirk in ColdFusion's Query of Queries (QoQ) engine.When you perform a UNION ALL across queries where a character column has a dynamic or varying string length (like your concatenated m.dimension_1_name + 'x'), QoQ identifies the longest string in that column across all result sets. It then treats the column like a fixed-length CHAR database field and pads all shorter values with trailing spaces to match that maximum length. --->
|
||||
<!--- лучше никогда не связываться с QoQ, но если все исполнять в исходной бд, это скорее мегаселект с большим числом CTE --->
|
||||
<!--- надо было сразу делать в БД. Причем сводить в одну, чтобы избежать нескольких источников данных... можно было бы и так добиться, но все равно сводим в буферную базу --->
|
||||
|
||||
<!--- <cfdump var=#qUnifiedMetric#/> --->
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
qUnifiedMetric
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qUnifiedMetric#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
|
||||
<!--- умножаем на цену, вычисляем дисконт (довольно поздно) и форматируем
|
||||
*** здесь нужно учесть версионность. Самым простым кажется декомпозировать по дням и снова собрать
|
||||
*** только как нам это сделать без нормального SQL движка
|
||||
Может быть, процедурная обработка не будет выглядеть ужасно, и не хуже SQL
|
||||
В конце концов, можно просто В ЦИКЛЕ обсчитать диапазон по дням, выполнив запрос 30 раз, или сколько надо
|
||||
Если будет тупить - оптимизируем
|
||||
--->
|
||||
|
||||
<!--- Для декомпозиции на более мелкие объекты мы можем как полумеру - профильтровать по конкретному бакету или ВМ-ВДЦ
|
||||
Что не нравится - для ВМ у нас может быть целое дерево нижележащих объектов вместо линейного списка бакетов --->
|
||||
|
||||
<!--- Вычитание Free Tier можно начинать с начала месяца - для этого можно сгруппировать по месяцам --->
|
||||
<!--- Кажется, здесь еще рано агрегировать, если мы хотим OUTER JOIN --->
|
||||
<!--- агрегировать вообще не надо в этом компоненте, а стоимость вычислять после агрегации --->
|
||||
<cfquery name="qChargeDaily" dbType="query">
|
||||
SELECT
|
||||
<d:field_set titleMapOut="titleMap" lengthOut="fieldCount">
|
||||
<d:field title="Код компонента">s.code as s_code</d:field>
|
||||
<d:field title="Код метрики">m.code as m_code</d:field>
|
||||
<d:field title="Код услуги">s.service_code as service_code</d:field>
|
||||
<d:field title="Услуга">s.svc</d:field>
|
||||
<d:field title="Компонент">s.component</d:field>
|
||||
<d:field title="Ед.изм.">m.unit</d:field>
|
||||
<d:field title="Цена &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">
|
||||
s.price*(100-s.discount)/100 as discounted_price
|
||||
</d:field>
|
||||
<d:field title="Цена с НДС" cfSqlType="CF_SQL_NUMERIC">s.price</d:field>
|
||||
<d:field title="Скидка%" cfSqlType="CF_SQL_NUMERIC">s.discount</d:field>
|
||||
<d:field title="Сырая метрика" cfSqlType="CF_SQL_NUMERIC">m.raw_metric</d:field>
|
||||
<d:field title="Приведенная метрика" cfSqlType="CF_SQL_NUMERIC">m.metric</d:field>
|
||||
<d:field title="serviceStart" cfSqlType="CF_SQL_TIMESTAMP">s.serviceStart</d:field>
|
||||
<d:field title="serviceEnd" cfSqlType="CF_SQL_TIMESTAMP">s.serviceEnd</d:field>
|
||||
<d:field title="serviceHash">s.serviceHash</d:field>
|
||||
<d:field title="serviceCustomName">s.serviceCustomName</d:field>
|
||||
<d:field title="dt" cfSqlType="CF_SQL_TIMESTAMP">m.dt</d:field>
|
||||
<d:field title="free tier" cfSqlType="CF_SQL_NUMERIC">s.free_tier</d:field>
|
||||
<d:field>m.dimension_1</d:field>
|
||||
<d:field>m.dimension_1_name</d:field>
|
||||
<d:field>m.dimension_2</d:field>
|
||||
<d:field>m.dimension_2_name</d:field>
|
||||
</d:field_set>
|
||||
FROM qSpec as s, qUnifiedMetric as m
|
||||
WHERE s.code=m.code
|
||||
AND s.serviceStart <= m.dt
|
||||
AND (m.dt <= s.serviceEnd OR s.serviceEnd IS NULL)
|
||||
<cfif #attributes.restrict_to_own_instances#>
|
||||
AND m.wz=<cfqueryparam cfsqltype="cf_sql_varchar" value=#request.auth.wz#/>
|
||||
</cfif>
|
||||
<!--- таким замысловатым способом мы реализуем FULL JOIN --->
|
||||
UNION ALL
|
||||
|
||||
SELECT NULL, m.code, NULL, NULL, NULL, NULL, 0,
|
||||
NULL, NULL, m.raw_metric, m.metric, NULL, NULL, NULL, NULL, m.dt, 0, m.dimension_1, m.dimension_1_name, m.dimension_2, m.dimension_2_name
|
||||
FROM qUnifiedMetric as m
|
||||
WHERE m.code NOT IN (<cfqueryparam value="#ValueList(qSpec.code)#" cfsqltype="cf_sql_varchar" list="true">)
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT s.code, NULL, s.service_code, s.svc, s.component, s.unit, s.price*(100-s.discount)/100 as discounted_price,
|
||||
s.price, s.discount, NULL, NULL, s.serviceStart, s.serviceEnd, s.serviceHash, s.serviceCustomName, NULL, 0, NULL, NULL, NULL, NULL
|
||||
FROM qSpec as s
|
||||
WHERE s.code NOT IN (<cfqueryparam value="#listRemoveDuplicates(ValueList(qUnifiedMetric.code))#" cfsqltype="cf_sql_varchar" list="true">)
|
||||
|
||||
ORDER by dt, s_code, m_code, dimension_1, dimension_2
|
||||
</cfquery>
|
||||
<!--- диагностика ошибок в QoQ крайне невнятна и вводит в заблуждение --->
|
||||
|
||||
<!---<cfdump var=#qChargeDaily# abort=true/> --->
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
qChargeDaily
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qChargeDaily#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<!--- Из-за детализации придется вынести вычитание free_tier на более поздний этап --->
|
||||
<!--- Здесь агрегировано за месяц, но детализировано по измерениям --->
|
||||
<cfquery name="qChargeMonthly" dbType="query">
|
||||
SELECT
|
||||
<d:field_set titleMapOut="chargeTitleMap" lengthOut="chargeFieldCount">
|
||||
<d:field title="Артикул по договору">s_code</d:field>
|
||||
<d:field title="Артикул по системам">m_code</d:field>
|
||||
<d:field title="Артикул">s_code as code</d:field>
|
||||
<d:field title="Код услуги">service_code</d:field>
|
||||
<d:field title="Услуга по каталогу">svc</d:field>
|
||||
<d:field title="serviceCustomName">serviceCustomName</d:field>
|
||||
<d:field title="Компонент">component</d:field>
|
||||
<d:field title="Ед.изм.">unit</d:field>
|
||||
<d:field title="Цена &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">discounted_price</d:field>
|
||||
<d:field title="Сырая метрика" cfSqlType="CF_SQL_NUMERIC">sum(raw_metric) as raw_metric</d:field>
|
||||
<d:field title="Приведенный объем" cfSqlType="CF_SQL_NUMERIC">sum(metric) as metric</d:field>
|
||||
<d:field title="serviceStart" cfSqlType="CF_SQL_TIMESTAMP">serviceStart</d:field>
|
||||
<d:field title="serviceEnd" cfSqlType="CF_SQL_TIMESTAMP">serviceEnd</d:field>
|
||||
<d:field title="dt_billed_from" cfSqlType="CF_SQL_TIMESTAMP">min(dt) as dt_billed_from</d:field>
|
||||
<d:field title="dt_billed_to" cfSqlType="CF_SQL_TIMESTAMP">max(dt) as dt_billed_to</d:field>
|
||||
<d:field title="serviceHash">serviceHash</d:field>
|
||||
<d:field title="free tier" cfSqlType="CF_SQL_NUMERIC">free_tier</d:field>
|
||||
<d:field>dimension_1</d:field>
|
||||
<d:field>dimension_1_name</d:field>
|
||||
<d:field>dimension_2</d:field>
|
||||
<d:field>dimension_2_name</d:field>
|
||||
<d:field title="Год" cfSqlType="CF_SQL_INTEGER">year(dt) as year</d:field>
|
||||
<d:field title="Месяц" cfSqlType="CF_SQL_INTEGER">month(dt) as month</d:field>
|
||||
</d:field_set>
|
||||
from qChargeDaily
|
||||
group by s_code, m_code, svc, service_code, serviceCustomName, component, unit, discounted_price, serviceStart, ServiceEnd, serviceHash, free_tier, year(dt), month(dt),
|
||||
dimension_1_name, dimension_1, dimension_2_name, dimension_2
|
||||
order by year(dt), month(dt), m_code, code, serviceStart, dimension_1, dimension_2
|
||||
</cfquery>
|
||||
<!--- в связи с бедностью языка QoQ (нет CASE) грубо патчим резалтсет --->
|
||||
<cfloop query="qChargeMonthly">
|
||||
<cfset qChargeMonthly.code = (len(code) GT 0) ? code : m_code/><!--- имя в левой части должно быть квалифицировано запросом (резалтсетом) --->
|
||||
</cfloop>
|
||||
|
||||
|
||||
<!--- тут могут быть подводные камни с копированием и переиспользованием объектов --->
|
||||
<!--- <cfif isQuery(qTotal)>
|
||||
<cfquery name="qTotalNew" dbType="query">
|
||||
select * from qTotal
|
||||
union all
|
||||
select * from qCharge
|
||||
</cfquery>
|
||||
<cfset qTotal = qTotalNew/>
|
||||
<cfelse>
|
||||
<cfset qTotal = qCharge/>
|
||||
</cfif>
|
||||
<cfdump var=#qTotal#/> --->
|
||||
|
||||
<!--- <cfdump var=#qChargeMonthly#/> --->
|
||||
<!--- *** проверить краевые даты --->
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
qChargeMonthly
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qChargeMonthly#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<!--- <cfflush/> --->
|
||||
|
||||
|
||||
|
||||
<cfset var report={}/>
|
||||
|
||||
<cfset report.qComputingAge = qComputingAge/>
|
||||
<cfset report.qStorageAge = qStorageAge/>
|
||||
<cfset report.qS3VolAge = qS3VolAge/>
|
||||
<cfset report.qS3OpsTrfAge = qS3OpsTrfAge/>
|
||||
<cfset report.qSpecification = qSpecification/>
|
||||
<cfset report.qCharge = qChargeMonthly/>
|
||||
<cfset report.qFreeTier = qFreeTier/><!--- мы не применяем скидку на уровне детализации, а только после агрегации. На самом деле правильно было бы агрегировать натуральные метрики, а умножать на цену уже агрегаты --->
|
||||
<cfset report.chargeTitleMap = chargeTitleMap/><!--- нужен для экспорта в XL --->
|
||||
<!--- <cfset report.chargeFieldCount = chargeFieldCount/> --->
|
||||
|
||||
<cfset "CALLER.#ATTRIBUTES.output#" = report/>
|
||||
|
||||
<cfexit method="exittag"/>
|
||||
@@ -0,0 +1,3 @@
|
||||
White label
|
||||
на экране логина предусматривать место для custom текста
|
||||
Помимо лого, предусматривать custom text
|
||||
@@ -0,0 +1,109 @@
|
||||
<cfimport prefix="m" taglib="../lib"/>
|
||||
<cfimport prefix="d" taglib="../lib/data"/>
|
||||
|
||||
<cfparam name="ATTRIBUTES.wz"/>
|
||||
<!--- <cfparam name="ATTRIBUTES.crm_cache_base" default="https://elma-cache.adl.nubes.ru/contract_ls.cfm"/> --->
|
||||
<cfparam name="ATTRIBUTES.out" default="qComponent"/>
|
||||
|
||||
<cfhttp method="get"
|
||||
url="#request.crm_cache_base#?wz=#ATTRIBUTES.wz#"
|
||||
timeout=10
|
||||
charset="utf-8"
|
||||
result="res"
|
||||
>
|
||||
</cfhttp>
|
||||
|
||||
<cfset local={}/>
|
||||
<!--- --->
|
||||
<cfset safeJsonString = REReplace(res.fileContent, '(:\s*)(-?\d+\.\d{16,})', '$1"$2"', "ALL")/><!--- очень длинные числа завернуть в кавычки --->
|
||||
<!--- <cfdump var=#safeJsonString#/> --->
|
||||
<cftry>
|
||||
<cfset company=deserializeJson(safeJsonString)/>
|
||||
<cfcatch type="ANY">
|
||||
Cannot deserialize CRM response
|
||||
|
||||
result:
|
||||
<cfdump var=#res#/>
|
||||
safeJsonString:
|
||||
<cfdump var=#safeJsonString#/>
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
<!---<cfset company=deserializeJson(res.fileContent)/> --->
|
||||
<!---<cfdump var=#company#/> --->
|
||||
<!--- *** это не слишком надежно, некорректно представленный NULL (обыкновенно представляемый пустой строкой) может все сломать. Да и корректный --->
|
||||
<!--- мартышкин труд собирать этот запрос из JSON , может, лучше было динамически --->
|
||||
<cfset qComponent = queryNew("
|
||||
contractId
|
||||
,contractOutsideId
|
||||
|
||||
,additionalAgreementId
|
||||
,additionalAgreementName
|
||||
|
||||
,dealIndex
|
||||
,serviceId
|
||||
,serviceType
|
||||
,catalogName
|
||||
,serviceCode
|
||||
,serviceCustomName
|
||||
,serviceStart
|
||||
,serviceEnd
|
||||
,serviceDiscount
|
||||
,serviceQuantity
|
||||
,serviceHash
|
||||
|
||||
,paramId
|
||||
,componentCode
|
||||
,component
|
||||
,measureShort
|
||||
,quantity
|
||||
,priceWVat
|
||||
,discount
|
||||
,atomicCode
|
||||
,fullCode
|
||||
",
|
||||
"varChar,varChar,varChar,varChar,integer,varChar,integer,varChar,varChar,varChar,timestamp,timestamp,decimal,decimal,varChar,integer,varChar,varChar,varChar,decimal,decimal,decimal,varChar,varChar")/>
|
||||
<!--- если не указывать типы, он пытается их определить сам, потом проблемы с union и арифметикой --->
|
||||
|
||||
<!--- this.nullSupport = true in Application.cfc ... no way --->
|
||||
<cfloop array=#company.contracts# item="local.contract"><!--- имя массива писать в ##, иначе думает, что это строковый литерал --->
|
||||
<cfloop array=#local.contract.additionalAgreements# item="local.additionalAgreement">
|
||||
<cfif NOT local.additionalAgreement.isActual><cfcontinue/></cfif>
|
||||
<cfloop array=#local.additionalAgreement.services# item="local.service">
|
||||
<cfloop array=#local.service.components# item="local.component">
|
||||
<cfset queryAddRow(qComponent, [{
|
||||
contractId=local.contract.contractId,
|
||||
contractOutsideId=local.contract.contractOutsideId,
|
||||
|
||||
additionalAgreementId=local.additionalAgreement.additionalAgreementId,
|
||||
additionalAgreementName=local.additionalAgreement.additionalAgreementName,
|
||||
|
||||
dealIndex=local.service.dealIndex ,
|
||||
serviceId=local.service.serviceId ,
|
||||
serviceType=local.service.serviceType,
|
||||
catalogName=local.service.catalogName,
|
||||
serviceCode=local.service.serviceCode,
|
||||
serviceCustomName=local.service.serviceCustomName,
|
||||
serviceStart=parseDateTime(local.service.serviceStart.ts),
|
||||
serviceEnd=isDate(structGet("local.service.serviceEnd.ts"))? parseDateTime(local.service.serviceEnd.ts):javacast('null',''),
|
||||
serviceDiscount=local.service.discount,
|
||||
serviceQuantity=local.service.quantity,
|
||||
serviceHash=local.service.serviceHash,
|
||||
|
||||
paramId=local.component.paramId,
|
||||
componentCode=local.component.componentCode,
|
||||
component=local.component.component,
|
||||
measureShort=local.component.measureShort,
|
||||
quantity=local.component.quantity,
|
||||
priceWVat=local.component.priceWVat,
|
||||
discount=local.component.discount,
|
||||
atomicCode=local.component.atomicCode,
|
||||
fullCode="#local.component.componentCode#-#listGetAt('i,f,m',local.service.serviceType)#"
|
||||
}])/>
|
||||
</cfloop>
|
||||
</cfloop>
|
||||
</cfloop>
|
||||
</cfloop>
|
||||
|
||||
<!--- <cfdump var=#qComponent#/> --->
|
||||
<cfset "CALLER.#ATTRIBUTES.out#" = qComponent/>
|
||||
<cfexit method="exittag"/>
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
SQL SELECT
|
||||
s.code,m.code as m_code,s.service_code as service_code,s.svc,s.component,s.unit,
|
||||
s.price*(100-s.discount)/100 as discounted_price
|
||||
,s.price,s.discount,m.raw_metric,m.metric,s.serviceStart,s.serviceEnd,s.serviceHash,s.serviceCustomName,m.dt,s.free_tier,m.dimension_1,m.dimension_1_name ||'x' as dimension_1_name,m.dimension_2,m.dimension_2_name
|
||||
FROM qSpec as s, qUnifiedMetric as m
|
||||
WHERE m.wz='62'
|
||||
AND s.code=m.code
|
||||
AND s.serviceStart <= m.dt
|
||||
AND (m.dt <= s.serviceEnd OR s.serviceEnd IS NULL)
|
||||
|
||||
|
||||
UNION ALL
|
||||
SELECT NULL, m.code, NULL, NULL, NULL, NULL, 0,
|
||||
NULL, NULL, m.raw_metric, m.metric, NULL, NULL, NULL, NULL, m.dt, 0, m.dimension_1, m.dimension_1_name ||'y', m.dimension_2, m.dimension_2_name
|
||||
FROM qUnifiedMetric as m where m.code NOT IN ('5','6')
|
||||
|
||||
UNION ALL
|
||||
SELECT s.code, NULL, s.service_code, s.svc, s.component, s.unit, s.price*(100-s.discount)/100 as discounted_price,
|
||||
s.price, s.discount, NULL, NULL, s.serviceStart, s.serviceEnd, s.serviceHash, s.serviceCustomName, NULL, 0, NULL, NULL, NULL, NULL
|
||||
FROM qSpec as s where s.code NOT IN ('5','6')
|
||||
order by m.dt, m.code, dimension_1, dimension_2
|
||||
@@ -5,25 +5,46 @@
|
||||
<cfparam name="ATTRIBUTES.dt_start" type="date" default=#dateAdd('m',-1,ATTRIBUTES.dt_finish)#/>
|
||||
<cfparam name="ATTRIBUTES.output" type="string" default="report"/>
|
||||
<cfparam name="ATTRIBUTES.debug" type="boolean" default=false/>
|
||||
<cfparam name="ATTRIBUTES.tenant_wz_index" type="string"/>
|
||||
|
||||
|
||||
<cfset hours=dateDiff('h', ATTRIBUTES.dt_start, ATTRIBUTES.dt_finish)/>
|
||||
<cfset tenant_wz_index=val(mid(request.auth.wz,3,5))/><!--- cut off WZ --->
|
||||
|
||||
|
||||
<!--- QoQ does not support join syntax, at least of Lucee 5.4--->
|
||||
|
||||
<!--- QoQ does not support join syntax, and of course outer joins, at least of Lucee 5.4--->
|
||||
<!--- а внешние джойны хорошо подсвечивают ошибки, особенно помогает full --->
|
||||
|
||||
<cfmodule template="crm_contract.cfm" wz="WZ01348" out="qSpecification"/>
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qSpecification#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<!--- Для начала выкатываем просто кусок каталога, не фильтруя по спеке (которой иногда нет) --->
|
||||
<cfquery name="qSpec">
|
||||
<!--- <cfquery name="qSpec">
|
||||
select * from (
|
||||
values
|
||||
('Объектное хранилище S3 CEPH','Дисковое пространство: Объем хранения','paas.s3.ceph.vol-m','ГБайт',1.80,0)
|
||||
,('Объектное хранилище S3 CEPH','Исходящий трафик','paas.s3.ceph.trf-m','ГБайт',1.50,0)
|
||||
,('Объектное хранилище S3 CEPH','Запросы GET, HEAD, OPTIONS','paas.s3.ceph.get-m','10тыс.шт.',0.35,0)
|
||||
,('Объектное хранилище S3 CEPH','Запросы PUT, POST, PATCH','paas.s3.ceph.put-m','10тыс.шт.',4.50,0)
|
||||
('Объектное хранилище S3 CEPH','Дисковое пространство: Объем хранения (HOT)','paas.s3.ceph.vol-m','ГБайт',1.80,0)
|
||||
,('Объектное хранилище S3 CEPH','Исходящий трафик (HOT)','paas.s3.ceph.trf-m','ГБайт',1.50,0)
|
||||
,('Объектное хранилище S3 CEPH','Запросы GET, HEAD, OPTIONS (HOT)','paas.s3.ceph.get-m','10тыс.шт.',0.35,0)
|
||||
,('Объектное хранилище S3 CEPH','Запросы PUT, POST, PATCH (HOT)','paas.s3.ceph.put-m','10тыс.шт.',4.50,0)
|
||||
|
||||
,('Объектное хранилище S3 CEPH','Дисковое пространство: Объем хранения (COLD)','paas.s3.cphc.vol-m','ГБайт',0.84*1.2,0)
|
||||
,('Объектное хранилище S3 CEPH','Исходящий трафик (COLD)','paas.s3.cphc.trf-m','ГБайт',1.25*1.2,0)
|
||||
,('Объектное хранилище S3 CEPH','Запросы GET, HEAD, OPTIONS (COLD)','paas.s3.cphc.get-m','10тыс.шт.',0.8*1.2,0)
|
||||
,('Объектное хранилище S3 CEPH','Запросы PUT, POST, PATCH (COLD)','paas.s3.cphc.put-m','10тыс.шт.',9.7*1.2,0)
|
||||
) as
|
||||
s (svc, component, code, unit, price, discount)
|
||||
order by code
|
||||
</cfquery> --->
|
||||
<!--- здесь нужно организовать пересечение версионной спецификации с анализируемым диапазоном дат --->
|
||||
<cfquery name="qSpec" dbtype="query">
|
||||
select catalogName as svc, component, fullCode as code, measureShort as unit
|
||||
, priceWVat as price, (discount + serviceDiscount - discount*serviceDiscount/100) as discount
|
||||
,serviceStart, serviceEnd
|
||||
from qSpecification
|
||||
</cfquery>
|
||||
|
||||
|
||||
@@ -41,7 +62,7 @@
|
||||
from ngcloud_ru.capacity_resource
|
||||
join ngcloud_ru.vdc on capacity_resource.vdc_id=vdc.id
|
||||
join ngcloud_ru.tenant on tenant.id=vdc.tenant_id
|
||||
where tenant.wzcode = <cfqueryparam cfsqltype="cf_sql_integer" value=#tenant_wz_index#/>
|
||||
where tenant.wzcode = <cfqueryparam cfsqltype="cf_sql_integer" value=#ATTRIBUTES.tenant_wz_index#/>
|
||||
AND capacity_resource.timestamp >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_start#/>
|
||||
AND capacity_resource.timestamp < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_finish#/>
|
||||
group by tenant.wzcode, vdc.name
|
||||
@@ -49,6 +70,7 @@
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qComputing#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
@@ -57,6 +79,12 @@
|
||||
select max(capacity_resource.timestamp) as dt_load from ngcloud_ru.capacity_resource
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qComputingAge#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
|
||||
<!--- переделать storage_profile_types с расшифровкой ssd, sata, можно прямо до каталожного кода --->
|
||||
<cfquery name="qStorage">
|
||||
@@ -80,7 +108,7 @@
|
||||
join ngcloud_ru.vdc on capacity_storage.vdc_id=vdc.id
|
||||
join ngcloud_ru.tenant on tenant.id=vdc.tenant_id
|
||||
join ngcloud_ru.storage_profile_types on capacity_storage.storage_profile_types_id=storage_profile_types.id
|
||||
where tenant.wzcode = <cfqueryparam cfsqltype="cf_sql_integer" value=#tenant_wz_index#/>
|
||||
where tenant.wzcode = <cfqueryparam cfsqltype="cf_sql_integer" value=#ATTRIBUTES.tenant_wz_index#/>
|
||||
AND capacity_storage.timestamp >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_start#/>
|
||||
AND capacity_storage.timestamp < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_finish#/>
|
||||
group by tenant.wzcode, vdc.name, storage_profile_types.name
|
||||
@@ -91,6 +119,7 @@
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qStorage#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
@@ -118,7 +147,7 @@ HOT_FREE_LIMIT 1 10 1 100
|
||||
join s3billing.placement ON s3billing.placement.id=bucket_stat.placement_id
|
||||
join s3billing.bucket_info ON bucket_info.id=bucket_stat.bucket_id
|
||||
where bucket_stat.placement_id in (1,2)
|
||||
AND bucket_stat.owner = <cfqueryparam cfsqltype="cf_sql_varchar" value=#tenant_wz_index#/>
|
||||
AND bucket_stat.owner = <cfqueryparam cfsqltype="cf_sql_varchar" value=#ATTRIBUTES.tenant_wz_index#/>
|
||||
AND bucket_stat.timestamp_addition >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_start#/>
|
||||
AND bucket_stat.timestamp_addition < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_finish#/>
|
||||
group by bucket_stat.owner, bucket_stat.placement_id
|
||||
@@ -126,6 +155,7 @@ HOT_FREE_LIMIT 1 10 1 100
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qS3Vol#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
@@ -134,6 +164,12 @@ HOT_FREE_LIMIT 1 10 1 100
|
||||
select max(timestamp_addition) as dt_load from s3billing.bucket_stat
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qS3VolAge#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<cfquery name="qS3OpsTrf">
|
||||
select
|
||||
sum(
|
||||
@@ -203,7 +239,7 @@ select
|
||||
join s3billing.bucket_info on usage_bucket_by_user.bucketid=bucket_info.id
|
||||
join s3billing.placement on bucket_info.placement_id=placement.id
|
||||
where 1=1
|
||||
AND user_info.name = <cfqueryparam cfsqltype="cf_sql_varchar" value=#tenant_wz_index#/>
|
||||
AND user_info.name = <cfqueryparam cfsqltype="cf_sql_varchar" value=#ATTRIBUTES.tenant_wz_index#/>
|
||||
AND usage_bucket_by_user.time >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_start#/>
|
||||
AND usage_bucket_by_user.time < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_finish#/>
|
||||
group by user_info.name, bucket_info.placement_id
|
||||
@@ -211,6 +247,7 @@ select
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qS3OpsTrf#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
@@ -219,7 +256,13 @@ select
|
||||
select max(time) as dt_load from s3billing.usage_bucket_by_user
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qS3OpsTrfAge#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<!--- собрали все метрики в один резалтсет --->
|
||||
<cfquery name="qUnifiedMetric" dbType="query">
|
||||
select wz, code || '.vcpu-m' as code, core_h as raw_metric, core_h as metric, core_h as chargeable_metric from qComputing
|
||||
union all
|
||||
@@ -237,14 +280,30 @@ select wz, code || '.trf-m', bytes_sent as raw_metric, bytes_sent_gb as metric,
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qUnifiedMetric#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<!--- умножаем на цену, вычисляем дисконт (довольно поздно) и форматируем
|
||||
*** здесь нужно учесть версионность. Самым простым кажется декомпозировать по дням и снова собрать
|
||||
*** только как нам это сделать без нормального SQL движка
|
||||
Может быть, процедурная обработка не будет выглядеть ужасно, и не хуже SQL
|
||||
В конце концов, можно просто В ЦИКЛЕ обсчитать диапазон по дням, выполнив запрос 30 раз, или сколько надо
|
||||
Если будет тупить - оптимизируем
|
||||
--->
|
||||
|
||||
<!--- Для декомпозиции на более мелкие объекты мы можем как полумеру - профильтровать по конкретному бакету или ВМ-ВДЦ
|
||||
Что не нравится - для ВМ у нас может быть целое дерево нижележащих объектов --->
|
||||
|
||||
<cfloop from=#attribute.dt_start# to=#attribute.dt_finish# index="dt">
|
||||
</cfloop>
|
||||
|
||||
<cfquery name="qCharge" dbType="query">
|
||||
SELECT
|
||||
<d:field_set titleMapOut="titleMap" lengthOut="fieldCount">
|
||||
<d:field title="Артикул">s.code</d:field>
|
||||
<d:field title="Артикул">m.code as m_code</d:field>
|
||||
<d:field title="Услуга">s.svc</d:field>
|
||||
<d:field title="Компонент">s.component</d:field>
|
||||
<d:field title="Кол-во (метрика)" cfSqlType="CF_SQL_NUMERIC">m.chargeable_metric</d:field>
|
||||
@@ -254,7 +313,7 @@ SELECT
|
||||
<!--- <d:field title="Дата НОУ" cfSqlType="CF_SQL_TIMESTAMP">s.dt_from</d:field> --->
|
||||
<!--- <d:field title="Дата оконч." cfSqlType="CF_SQL_TIMESTAMP">s.dt_to</d:field>
|
||||
<d:field title="Ключ строки">s.line_key</d:field> --->
|
||||
<d:field title="GPL с НДС" cfSqlType="CF_SQL_NUMERIC">s.price</d:field>
|
||||
<d:field title="Цена с НДС" cfSqlType="CF_SQL_NUMERIC">s.price</d:field>
|
||||
<d:field title="Скидка%" cfSqlType="CF_SQL_NUMERIC">s.discount</d:field>
|
||||
<d:field title="Сырая метрика" cfSqlType="CF_SQL_NUMERIC">m.raw_metric</d:field>
|
||||
<d:field title="Приведенная метрика" cfSqlType="CF_SQL_NUMERIC">m.metric</d:field>
|
||||
@@ -266,6 +325,12 @@ WHERE m.wz=<cfqueryparam cfsqltype="cf_sql_varchar" value=#request.auth.wz#/> AN
|
||||
order by s.code
|
||||
</cfquery>
|
||||
|
||||
<cfif (ATTRIBUTES.debug)>
|
||||
<cfoutput>#getTickCount() - request.startTickCount#</cfoutput>
|
||||
<cfdump var=#qCharge#/>
|
||||
<cfflush/>
|
||||
</cfif>
|
||||
|
||||
<cfset var report={}/>
|
||||
|
||||
<cfset report.qComputingAge = qComputingAge/>
|
||||
@@ -0,0 +1,318 @@
|
||||
<cfsilent>
|
||||
<cfimport prefix="m" taglib="lib"/>
|
||||
<cfimport prefix="c" taglib="lib/controls"/>
|
||||
<cfimport prefix="d" taglib="lib/data"/>
|
||||
<cfimport prefix="layout" taglib="layout"/>
|
||||
</cfsilent>
|
||||
|
||||
<m:prepare_ls entity="payg" accessObject="" pageInfoOut="pageInfo" trackOut="tr"/>
|
||||
|
||||
<cfparam name="dt_finish" type="date" default=#dateAdd('d',-1,createDateTime(year(Now()),month(Now()),1,0,0,0))#/>
|
||||
<cfparam name="dt_start" type="date" default=#dateAdd('m',-1,createDateTime(year(Now()),month(Now()),1,0,0,0))#/>
|
||||
|
||||
<cfset hours=dateDiff('h', dt_start, dateAdd('d', 1, dt_finish))/>
|
||||
|
||||
<cfset restrict_to_own_instances = true>
|
||||
<cfparam name="WZ" default=#request.auth.wz#/>
|
||||
<cfif request.auth.wz EQ 'WZ01112'><!--- грубо --->
|
||||
<cfset restrict_to_own_instances = false>
|
||||
<cfelse>
|
||||
<cfset WZ=request.auth.wz/><!--- без баловства --->
|
||||
</cfif>
|
||||
<cfset tenant_wz_index=val(mid(WZ,3,5))/><!--- cut off WZ --->
|
||||
|
||||
|
||||
<cfif isDefined("output_xls")><cfmodule template="mod/compute_payg.cfm"
|
||||
dt_finish=#dt_finish#
|
||||
dt_start=#dt_start#
|
||||
tenant_wz_index=#tenant_wz_index#
|
||||
output="report"
|
||||
debug=#isDefined("DEBUG")#
|
||||
restrict_to_own_instances=#restrict_to_own_instances#
|
||||
/>
|
||||
<layout:xml qRead=#report.qCharge# titleMap=#report.chargeTitleMap# filename="#pageInfo.entity#.xml"/>
|
||||
<cfabort/>
|
||||
</cfif><cfif isDefined("output_json")><cfmodule template="mod/compute_payg.cfm"
|
||||
dt_finish=#dt_finish#
|
||||
dt_start=#dt_start#
|
||||
tenant_wz_index=#tenant_wz_index#
|
||||
output="report"
|
||||
debug=#isDefined("DEBUG")#
|
||||
restrict_to_own_instances=#restrict_to_own_instances#
|
||||
/><!--- <cfdump var=#report#/><cfabort/> ---><layout:json qRead=#report.qCharge# titleMap=#report.chargeTitleMap# filename="#pageInfo.entity#.json"/>
|
||||
<cfabort/>
|
||||
</cfif><!---
|
||||
---><layout:page section="header" pageInfo=#pageInfo#>
|
||||
|
||||
<layout:attribute name="title">
|
||||
<cfoutput><b>Отчет по PAYG</b> #WZ#</cfoutput>
|
||||
</layout:attribute>
|
||||
<layout:attribute name="controls">
|
||||
<!---skip filter link, filter is not implemented--->
|
||||
<!---<layout:language_switch/>--->
|
||||
</layout:attribute>
|
||||
</layout:page>
|
||||
|
||||
<!--- Внимание! округление вверх при расчете метрик get, put S3. Расчетные суммы могут содержать погрешности округления, поэтому окончательный расчет стоимости (количество * цену) выполняeтся в бухгалтерской программе.
|
||||
<b>Если у клиента больше 1 действующего допника с услугами PAYG, то данные в отчете могут быть замножены, в этом случае считать вручную</b> --->
|
||||
|
||||
<cfoutput>
|
||||
<form method="post" action="#request.thisPage#" style="display:inline"><!--- не надо делать action="" - параметр, затесавшийся в URL будет затирать параметр формы, и заметить это трудно --->
|
||||
Период с <input type="text" name="dt_start" value="#dateFormat(dt_start,'YYYY-MM-DD')#"/>
|
||||
по <input type="text" name="dt_finish" value="#dateFormat(dt_finish,'YYYY-MM-DD')#"/>
|
||||
|
||||
<cfif request.auth.wz EQ 'WZ01112'><!--- очень грубо --->
|
||||
WZ <input type="text" name="wz" value="#WZ#"/>
|
||||
</cfif>
|
||||
|
||||
<input type="submit" style="cursor:pointer;"/>
|
||||
<input type="submit" name="DEBUG" value="DEBUG" style="cursor:pointer;"/><!--- ********* --->
|
||||
|
||||
|
||||
</form>
|
||||
<cfset month_start = createDate(year(now()), month(now()), 1)/>
|
||||
<a href="?dt_start=#dateFormat(dateAdd('m', -1, month_start),'YYYY-MM-DD')#&dt_finish=#dateFormat(dateAdd('d', -1, month_start),'YYYY-MM-DD')#&wz=#WZ#">
|
||||
прошлый месяц
|
||||
</a>
|
||||
<a href="?dt_start=#dateFormat(createDate(year(now()), month(now()), 1),'YYYY-MM-DD')#&dt_finish=#dateFormat(createDate(year(now()), month(now()), daysInMonth(now())),'YYYY-MM-DD')#&wz=#WZ#">
|
||||
текущий месяц
|
||||
</a>
|
||||
<br/>
|
||||
|
||||
<!--- <cfflush/> --->
|
||||
|
||||
<cfmodule template="mod/compute_payg.cfm"
|
||||
dt_finish=#dt_finish#
|
||||
dt_start=#dt_start#
|
||||
tenant_wz_index=#tenant_wz_index#
|
||||
output="report"
|
||||
debug=#structKeyExists(Form,"DEBUG")#
|
||||
restrict_to_own_instances=#restrict_to_own_instances#
|
||||
/>
|
||||
|
||||
Часов в периоде: <b>#hours#</b> Строк в отчете: <b>#report.qCharge.recordCount#</b><br/>
|
||||
Актуальность данных:
|
||||
VCD Computing: <b<cfif datediff("h",report.qComputingAge.dt_load, Now()) GT 24> class="err"</cfif>>
|
||||
#dateFormat(report.qComputingAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qComputingAge.dt_load,'HH:MM:SS')#
|
||||
</b>
|
||||
VCD Storage: <b<cfif datediff("h",report.qStorageAge.dt_load, Now()) GT 24> class="err"</cfif>>
|
||||
#dateFormat(report.qStorageAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qStorageAge.dt_load,'HH:MM:SS')#</b>
|
||||
S3 хранение: <b<cfif datediff("h",report.qS3VolAge.dt_load, Now()) GT 24> class="err"</cfif>>
|
||||
#dateFormat(report.qS3VolAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qS3VolAge.dt_load,'HH:MM:SS')#
|
||||
</b>
|
||||
S3 операции и трафик: <b<cfif datediff("h",report.qS3OpsTrfAge.dt_load, Now()) GT 24> class="err"</cfif>>
|
||||
#dateFormat(report.qS3OpsTrfAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qS3OpsTrfAge.dt_load,'HH:MM:SS')#
|
||||
</b>
|
||||
<br/>
|
||||
Цены по данным договора из CRM (через elma-cache). Учитываются метрики по S3, vCloud (кроме GPU). Внимание! количество за период *** округляется вверх, но делается это после всех агрегаций.
|
||||
<br/>
|
||||
|
||||
|
||||
<a href="#request.thisPage#?output_xls" title="экспорт в Excel" style="margin-left:.5em; height:100%;" target="_blank"><img src="img/xls.gif" style="vertical-align:text-bottom;"/></a>
|
||||
|
||||
<a href="#request.thisPage#?output_json" title="экспорт в json" style="margin-left:.5em; height:100%;" target="_blank"><img src="img/json.svg" style="vertical-align:text-bottom;" width="13" height="13"/></a>
|
||||
</cfoutput>
|
||||
<table class="worktable">
|
||||
<thead>
|
||||
<th width="1%"></th>
|
||||
<th width="7%" colspan="2">Артикул</th>
|
||||
<th width="3%">С</td>
|
||||
<th width="3%">По</td>
|
||||
<th width="3%">Кол-во (метрика)</td>
|
||||
<th width="3%">Free Tier</td>
|
||||
<th width="7%">Оплачиваемый объем</th>
|
||||
|
||||
<th width="3%">Ед.изм.</th>
|
||||
|
||||
<th width="3%">Цена ₽ с НДС</th>
|
||||
<th width="3%">Стоимость ₽ с НДС</th>
|
||||
|
||||
<th width="10%">Услуга</th>
|
||||
<th width="10%">Компонент</th>
|
||||
|
||||
<!--- <td width="10%">Клиентс. назв.</td> --->
|
||||
|
||||
<!--- <td width="3%">GPL с НДС</td>
|
||||
<td width="3%">Скидка%</td> --->
|
||||
|
||||
<!--- <td width="6%">Дата НОУ</td>
|
||||
<td width="6%">Дата оконч.</td>
|
||||
|
||||
<td width="3%">Ключ строки</td> --->
|
||||
<!--- <td width="3%">Сырая метрика</td> --->
|
||||
|
||||
|
||||
<!--- <td width="5%">Договор</td>
|
||||
<td width="10%">Допник</td>
|
||||
<td width="10%">Сделка</td> --->
|
||||
|
||||
</thead>
|
||||
|
||||
<!--- *** Обнаружена засада: возможно, группировка (сортировка) отображаемого вывода нужна по размерности детализации, а не по коду
|
||||
Но: агрегация скорее нужна по коду
|
||||
Видимо, придется на фронте перетасовывать?
|
||||
--->
|
||||
<!--- Еще засада: если я делегирую агрегацию на фронт, мне нужно и вычет free_tier делегировать на фронт (помня еще, что он на месяц, а не на произвольный период - наверно, можно его вычитать всегда, а больше месяца не агрегировать... или умножать на число полных месяцев) --->
|
||||
<!--- видимо, Free Tier и единицу измерения нужно брать и для строк, которые не найдены в договоре
|
||||
(еше можно было бы туда для полноты добавлять GPL цену, но для этого нужен каталог)
|
||||
Добавить реквизиты договора? --->
|
||||
<cfoutput query="report.qCharge" group="year">
|
||||
<cfoutput group="month">
|
||||
<tr><td colspan="99"><cfif month GT 0><b>#year#-#numberFormat(month,"00")#</b></cfif></td></tr>
|
||||
<cfoutput group="svc">
|
||||
<cfset var accum_cost_svc = 0/>
|
||||
<cfset var accum_metric_svc = 0/>
|
||||
<tr>
|
||||
<td bgcolor="##ccc"></td>
|
||||
<td bgcolor="##ccc" colspan="12">
|
||||
#svc# <b>#service_code#</b>
|
||||
<cfif len(serviceCustomName)>(#serviceCustomName#)</cfif>
|
||||
<cfif serviceHash EQ "">(не найдено в договоре)</cfif>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<cfoutput group="code">
|
||||
<cfoutput group="serviceStart"> <!--- может быть, для ясности надо в каждой строке писать точный период --->
|
||||
<cfset accum_metric_svc += isNumeric(metric) ? metric : 0/><!--- агрегация по метрике возможна только на уровне компонента --->
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan="10">#code# <cfif code EQ "">(#m_code#)</cfif></td>
|
||||
<td>#svc#</td>
|
||||
<td>#component# </td>
|
||||
</tr>
|
||||
|
||||
<cfset accum_metric_dimension_1 = 0/>
|
||||
|
||||
<cfoutput group="dimension_1">
|
||||
<cfset accum_metric_dimension_1 += isNumeric(metric) ? metric : 0/>
|
||||
<tr class="i">
|
||||
<td>#currentRow#</td>
|
||||
<td>#dimension_1_name#</td>
|
||||
<td>#dimension_1#</td>
|
||||
<td class="c">#dateFormat(dt_billed_from,"YYYY-MM-DD")#</td>
|
||||
<td class="c">#dateFormat(dt_billed_to,"YYYY-MM-DD")#</td>
|
||||
<td class="r"><cfif metric NEQ 0 AND isNumeric(metric)>#round(metric,3)#</cfif></td>
|
||||
<td><!--- free tier ---></td>
|
||||
<td class="r" style="font-size:120%; padding:0 1em;"></td>
|
||||
<td class="c">#unit#</td>
|
||||
<td class="r">#gaussianRound(discounted_price,2)#</td>
|
||||
<td class="r"><!--- здесь не вычисляется стоимость, потому что Free Tier вычитается после агрегации (скидочные политики реализовывать будет непросто) ---></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</cfoutput>
|
||||
|
||||
<cfset cost_dimension_1 = precisionEvaluate("gaussianRound(max(accum_metric_dimension_1 - free_tier, 0)*gaussianRound(discounted_price, 2), 2)")/>
|
||||
|
||||
<tr class="b">
|
||||
<td></td>
|
||||
<td colspan="4">Итого #code# <cfif code EQ "">(#m_code#)</cfif>:</td>
|
||||
<td class="r"><cfif accum_metric_dimension_1 NEQ 0 AND isNumeric(accum_metric_dimension_1)>#round(accum_metric_dimension_1,3)#</cfif></td>
|
||||
<td class="r">#free_tier#</td>
|
||||
<td class="r" style="font-size:120%; padding:0 1em;"><cfif accum_metric_dimension_1 NEQ 0 AND isNumeric(accum_metric_dimension_1)>#max(ceiling(accum_metric_dimension_1) - free_tier, 0)#</cfif></td>
|
||||
<td class="c">#unit#</td>
|
||||
<td class="r">#gaussianRound(discounted_price,2)#</td><!--- если цена менялась в периоде, неправильно показыввать последнюю - но мы не тестировали с изменением в периоде --->
|
||||
<!--- непонятно, как вычитать Free Tier для неполных месяцев. Если с 15 по 15 - вычитать 2 раза, вычитать (каким-то сложным образом) 1 раз или ни разу --->
|
||||
<!--- видимо, нужно сформировать тест кейсы на неполные месяцы. Где взять биллинговые данные для этого ВПР --->
|
||||
<td class="r">#cost_dimension_1#</td>
|
||||
<cfset accum_cost_svc = precisionEvaluate("accum_cost_svc + cost_dimension_1")/><!--- простое сложение дает ошибку округления и лишние знаки, но и precisionEvaluate не выглядит слишком надежным --->
|
||||
<td>#svc# <!--- #service_code# ---></td>
|
||||
<td>#component# </td>
|
||||
</tr>
|
||||
|
||||
</cfoutput><!--- serviceStart --->
|
||||
</cfoutput><!--- code --->
|
||||
<tr>
|
||||
<td bgcolor="##eee" style="border-bottom:2px solid gray;"></td>
|
||||
<td bgcolor="##eee" colspan="9" class="r" style="border-bottom:2px solid gray;">
|
||||
<b>Итого </b>
|
||||
<cfif len(service_code)>
|
||||
#svc# <b>#service_code#</b>
|
||||
<cfelse>
|
||||
(#m_code#)
|
||||
</cfif>
|
||||
<cfif month GT 0>за #year#-#numberFormat(month,"00")#</cfif>:
|
||||
</td>
|
||||
<td bgcolor="##eee" class="r b" style="border-bottom:2px solid gray;">#accum_cost_svc#</td>
|
||||
<td bgcolor="##eee" colspan="99" style="border-bottom:2px solid gray;"></td>
|
||||
</tr >
|
||||
</cfoutput>
|
||||
<tr><td colspan="99"> </td></tr>
|
||||
</cfoutput>
|
||||
</cfoutput>
|
||||
|
||||
</table>
|
||||
|
||||
<!--- <cfdump var=#report.qSpecification#/> --->
|
||||
<h3>Спецификация</h3>
|
||||
<table class="worktable">
|
||||
<tr>
|
||||
<th width="5%">Договор</th>
|
||||
<th width="15%">Доп. соглашение</th>
|
||||
<th width="3%">Тип оплаты</th>
|
||||
<th width="20%">Пользовательское наименование</th>
|
||||
<th width="3%">Кол-во по строке</th>
|
||||
<th width="3%">Скидка по строке</th>
|
||||
<th width="5%">НОУ</th>
|
||||
<th width="5%">КОУ</th>
|
||||
<th width="10%">Компонент</th>
|
||||
<th width="5%">Артикул</th>
|
||||
<th width="5%">Кол-во</th>
|
||||
<th width="5%">Ед.изм.</th>
|
||||
<th width="5%">Цена с НДС</th>
|
||||
<th width="5%">Скидка %</th>
|
||||
<th width="5%">Цена со скидкой с НДС</th>
|
||||
</tr>
|
||||
<cfoutput query="report.qSpecification">
|
||||
<tr>
|
||||
<td>#contractOutsideId#</td>
|
||||
<td>#additionalAgreementName#</td>
|
||||
<td class="c">#serviceType#</td>
|
||||
<td>#serviceCustomName#</td>
|
||||
<td class="c">#serviceQuantity#</td>
|
||||
<td class="r">#serviceDiscount#</td>
|
||||
<td class="c">#dateFormat(serviceStart, "YYYY-MM-DD")#</td>
|
||||
<td class="c">#dateFormat(serviceEnd, "YYYY-MM-DD")#</td>
|
||||
<td>#component#</td>
|
||||
<td>#componentCode#</td>
|
||||
<td class="r">#quantity#</td>
|
||||
<td class="c">#measureShort#</td>
|
||||
<td class="r">#gaussianRound(priceWVat,2)#</td>
|
||||
<td class="r">#discount#</td>
|
||||
<td class="r">#gaussianRound((100-serviceDiscount)/100*(100-discount)/100*priceWVat,4)#</td>
|
||||
</tr>
|
||||
</cfoutput>
|
||||
|
||||
</table>
|
||||
|
||||
<!---<cfdump var=#report.qCharge#/> --->
|
||||
<!--- <cfdump var=#this.datasources[request.ds].connectionString#/> --->
|
||||
|
||||
<layout:page section="footer"/>
|
||||
|
||||
<!--- select * from s3billing.billing_per_user_fix_pl('2025-05-01 00:00:00','2025-06-01 00:00:00','1395'); --->
|
||||
<cfscript>
|
||||
function gaussianRound(numeric number, numeric precision = 0) {
|
||||
var factor = 10 ^ precision;
|
||||
var scaledNumber = number * factor;
|
||||
var absScaled = abs(scaledNumber);
|
||||
var sign = sgn(scaledNumber);
|
||||
var floored = int(absScaled);
|
||||
|
||||
// If it's not ending in exactly .5, use standard rounding or precision scaling
|
||||
if (absScaled - floored != 0.5) {
|
||||
return round(number * factor) / factor;
|
||||
}
|
||||
|
||||
// If it is exactly .5, round towards the nearest even number
|
||||
if (floored % 2 != 0) {
|
||||
// Nearest even is UP
|
||||
return (floored + 1) * sign / factor;
|
||||
} else {
|
||||
// Nearest even is DOWN
|
||||
return floored * sign / factor;
|
||||
}
|
||||
}
|
||||
</cfscript>
|
||||
|
||||
Reference in New Issue
Block a user