File: server.rb

package info (click to toggle)
gitlab 17.6.5-19
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 629,368 kB
  • sloc: ruby: 1,915,304; javascript: 557,307; sql: 60,639; xml: 6,509; sh: 4,567; makefile: 1,239; python: 406
file content (140 lines) | stat: -rw-r--r-- 3,321 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# frozen_string_literal: true

module Gitaly
  class Server
    SHA_VERSION_REGEX = /\A\d+\.\d+\.\d+-\d+-g([a-f0-9]{8})\z/
    DEFAULT_REPLICATION_FACTOR = 1

    ServerSignature = Struct.new(:public_key, :error, keyword_init: true)

    class << self
      def all
        Gitlab.config.repositories.storages.keys.map { |s| Gitaly::Server.new(s) }
      end

      def count
        all.size
      end

      def filesystems
        all.map(&:filesystem_type).compact.uniq
      end

      def gitaly_clusters
        all.count { |g| g.replication_factor > DEFAULT_REPLICATION_FACTOR }
      end
    end

    attr_reader :storage

    def initialize(storage)
      @storage = storage
    end

    def server_version
      info.server_version
    end

    def git_binary_version
      info.git_version
    end

    def expected_version?
      server_version == Gitlab::GitalyClient.expected_server_version || matches_sha?
    end
    alias_method :up_to_date?, :expected_version?

    def read_writeable?
      readable? && writeable?
    end

    def readable?
      storage_status&.readable
    end

    def writeable?
      storage_status&.writeable
    end

    def filesystem_type
      storage_status&.fs_type
    end

    def server_signature_public_key
      server_signature&.public_key
    end

    def server_signature_error?
      !!server_signature.try(:error)
    end

    def disk_used
      disk_statistics_storage_status&.used
    end

    def disk_available
      disk_statistics_storage_status&.available
    end

    # Simple convenience method for when obtaining both used and available
    # statistics at once is preferred.
    def disk_stats
      disk_statistics_storage_status
    end

    def address
      Gitlab::GitalyClient.address(@storage)
    rescue RuntimeError => e
      "Error getting the address: #{e.message}"
    end

    def replication_factor
      storage_status&.replication_factor
    end

    private

    def storage_status
      @storage_status ||= info.storage_statuses.find { |s| s.storage_name == storage }
    end

    def disk_statistics_storage_status
      @disk_statistics_storage_status ||= disk_statistics.storage_statuses.find { |s| s.storage_name == storage }
    end

    def matches_sha?
      match = server_version.match(SHA_VERSION_REGEX)
      return false unless match

      Gitlab::GitalyClient.expected_server_version.start_with?(match[1])
    end

    def server_signature
      @server_signature ||= begin
        Gitlab::GitalyClient::ServerService.new(@storage).server_signature
      rescue GRPC::Unavailable, GRPC::DeadlineExceeded
        ServerSignature.new(public_key: nil, error: true)
      end
    end

    def info
      @info ||= wrapper_gitaly_rpc_errors do
        Gitlab::GitalyClient::ServerService.new(@storage).info
      end
    end

    def disk_statistics
      @disk_statistics ||= wrapper_gitaly_rpc_errors do
        Gitlab::GitalyClient::ServerService.new(@storage).disk_statistics
      end
    end

    def wrapper_gitaly_rpc_errors
      yield
    rescue GRPC::Unavailable, GRPC::DeadlineExceeded => ex
      Gitlab::ErrorTracking.track_exception(ex)
      # This will show the server as being out of date
      Gitaly::ServerInfoResponse.new(git_version: '', server_version: '', storage_statuses: [])
    end
  end
end