github.com/cs3org/reva/v2@v2.27.7/pkg/share/cache/warmup/cbox/cbox.go (about) 1 // Copyright 2018-2021 CERN 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // In applying this license, CERN does not waive the privileges and immunities 16 // granted to it by virtue of its status as an Intergovernmental Organization 17 // or submit itself to any jurisdiction. 18 19 package cbox 20 21 import ( 22 "context" 23 "database/sql" 24 "fmt" 25 26 userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" 27 rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" 28 provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" 29 "github.com/cs3org/reva/v2/pkg/auth/scope" 30 ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" 31 "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" 32 "github.com/cs3org/reva/v2/pkg/share/cache" 33 "github.com/cs3org/reva/v2/pkg/share/cache/warmup/registry" 34 "github.com/cs3org/reva/v2/pkg/token/manager/jwt" 35 "github.com/mitchellh/mapstructure" 36 "github.com/pkg/errors" 37 "google.golang.org/grpc/metadata" 38 39 // Provides mysql drivers 40 _ "github.com/go-sql-driver/mysql" 41 ) 42 43 func init() { 44 registry.Register("cbox", New) 45 } 46 47 type config struct { 48 DbUsername string `mapstructure:"db_username"` 49 DbPassword string `mapstructure:"db_password"` 50 DbHost string `mapstructure:"db_host"` 51 DbPort int `mapstructure:"db_port"` 52 DbName string `mapstructure:"db_name"` 53 EOSNamespace string `mapstructure:"namespace"` 54 GatewaySvc string `mapstructure:"gatewaysvc"` 55 JWTSecret string `mapstructure:"jwt_secret"` 56 } 57 58 type manager struct { 59 conf *config 60 db *sql.DB 61 } 62 63 func parseConfig(m map[string]interface{}) (*config, error) { 64 c := &config{} 65 if err := mapstructure.Decode(m, c); err != nil { 66 err = errors.Wrap(err, "error decoding conf") 67 return nil, err 68 } 69 return c, nil 70 } 71 72 // New returns an implementation of cache warmup that connects to the cbox share db and stats resources on EOS 73 func New(m map[string]interface{}) (cache.Warmup, error) { 74 c, err := parseConfig(m) 75 if err != nil { 76 return nil, err 77 } 78 db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", c.DbUsername, c.DbPassword, c.DbHost, c.DbPort, c.DbName)) 79 if err != nil { 80 return nil, err 81 } 82 83 return &manager{ 84 conf: c, 85 db: db, 86 }, nil 87 } 88 89 func (m *manager) GetResourceInfos() ([]*provider.ResourceInfo, error) { 90 query := "select coalesce(fileid_prefix, '') as fileid_prefix, coalesce(item_source, '') as item_source FROM oc_share WHERE (orphan = 0 or orphan IS NULL)" 91 rows, err := m.db.Query(query) 92 if err != nil { 93 return nil, err 94 } 95 defer rows.Close() 96 97 tokenManager, err := jwt.New(map[string]interface{}{ 98 "secret": m.conf.JWTSecret, 99 }) 100 if err != nil { 101 return nil, err 102 } 103 104 u := &userpb.User{ 105 Id: &userpb.UserId{ 106 OpaqueId: "root", 107 }, 108 UidNumber: 0, 109 GidNumber: 0, 110 } 111 scope, err := scope.AddOwnerScope(nil) 112 if err != nil { 113 return nil, err 114 } 115 116 tkn, err := tokenManager.MintToken(context.Background(), u, scope) 117 if err != nil { 118 return nil, err 119 } 120 ctx := metadata.AppendToOutgoingContext(context.Background(), ctxpkg.TokenHeader, tkn) 121 122 client, err := pool.GetGatewayServiceClient(m.conf.GatewaySvc) 123 if err != nil { 124 return nil, err 125 } 126 127 infos := []*provider.ResourceInfo{} 128 for rows.Next() { 129 var spaceID, nodeID string 130 if err := rows.Scan(&spaceID, &nodeID); err != nil { 131 continue 132 } 133 134 statReq := provider.StatRequest{Ref: &provider.Reference{ 135 ResourceId: &provider.ResourceId{ 136 SpaceId: spaceID, 137 OpaqueId: nodeID, 138 }, 139 }} 140 141 statRes, err := client.Stat(ctx, &statReq) 142 if err != nil || statRes.Status.Code != rpc.Code_CODE_OK { 143 continue 144 } 145 146 infos = append(infos, statRes.Info) 147 } 148 149 if err = rows.Err(); err != nil { 150 return nil, err 151 } 152 153 return infos, nil 154 155 }