• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

yast / yast-network / 11723621905

07 Nov 2024 01:07PM UTC coverage: 80.591% (+0.007%) from 80.584%
11723621905

Pull #1368

github

teclator
changes based on CR
Pull Request #1368: Assign the global default route to an specific connection when possible

20 of 20 new or added lines in 3 files covered. (100.0%)

5 existing lines in 2 files now uncovered.

9280 of 11515 relevant lines covered (80.59%)

19.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.75
/src/lib/y2network/connection_config/base.rb
1
# Copyright (c) [2019] SUSE LLC
2
#
3
# All Rights Reserved.
4
#
5
# This program is free software; you can redistribute it and/or modify it
6
# under the terms of version 2 of the GNU General Public License as published
7
# by the Free Software Foundation.
8
#
9
# This program is distributed in the hope that it will be useful, but WITHOUT
10
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12
# more details.
13
#
14
# You should have received a copy of the GNU General Public License along
15
# with this program; if not, contact SUSE LLC.
16
#
17
# To contact SUSE LLC about this file by physical or electronic mail, you may
18
# find current contact information at www.suse.com.
19

20
require "yast"
1✔
21
require "y2storage"
1✔
22
require "yast2/equatable"
1✔
23
require "y2network/ip_address"
1✔
24
require "y2network/interface_type"
1✔
25
require "y2network/boot_protocol"
1✔
26
require "y2network/startmode"
1✔
27
require "y2network/connection_config/ip_config"
1✔
28

29
Yast.import "Mode"
1✔
30

31
module Y2Network
1✔
32
  module ConnectionConfig
1✔
33
    # This class is reponsible of a connection configuration
34
    #
35
    # It holds a configuration (IP addresses, MTU, WIFI settings, etc.) that can be applied to an
36
    # interface. By comparison, it is the equivalent of the "Connection" concept in NetworkManager.
37
    # When it comes to sysconfig, a "ConnectionConfig" is defined using a "ifcfg-*" file.
38
    #
39
    # Additionally, each connection config gets an internal ID which makes easier to track changes
40
    # between two different {Y2Network::Config} objects. When they are copied, the same IDs are
41
    # kept, so it is easy to find out which connections have been added, removed or simply changed.
42
    class Base
1✔
43
      include Yast2::Equatable
1✔
44
      include Yast::Logger
1✔
45

46
      # A connection could belongs to a specific interface or not. In case of
47
      # no specific interface then it could be activated by the first available
48
      # device.
49
      #
50
      # @return [String] Connection name
51
      attr_accessor :name
1✔
52

53
      # @return [String, nil] Interface to apply the configuration to
54
      # FIXME: Maybe in the future it could be a matcher. By now we will use
55
      #   the interface's name.
56
      attr_accessor :interface
1✔
57

58
      # @return [BootProtocol] Bootproto
59
      attr_accessor :bootproto
1✔
60
      # @return [IPConfig, nil] Primary IP configuration
61
      attr_accessor :ip
1✔
62
      # @return [Array<IPConfig>] Additional IP configurations (also known as 'aliases')
63
      attr_accessor :ip_aliases
1✔
64
      # @return [Integer, nil]
65
      attr_accessor :mtu
1✔
66
      # @return [Startmode]
67
      attr_accessor :startmode
1✔
68
      # @return [String, nil] Connection's custom description (e.g., "Ethernet Card 0")
69
      attr_accessor :description
1✔
70
      # @return [String] Link layer address
71
      attr_accessor :lladdress
1✔
72
      # @return [String] configuration for ethtools when initializing
73
      attr_accessor :ethtool_options
1✔
74
      # @return [String] assigned firewall zone to interface
75
      attr_accessor :firewall_zone
1✔
76
      # @return [Array<String>] interface's hostnames
77
      attr_accessor :hostnames
1✔
78
      # @return [Boolean, nil] set to true if dhcp from this interface sets machine hostname,
79
      #   false if not and nil if not specified
80
      attr_accessor :dhclient_set_hostname
1✔
81

82
      # @return [String] Connection identifier
83
      attr_reader :id
1✔
84

85
      # @return [Integer] Connection identifier counter
86
      @@last_id = 0
1✔
87

88
      # Constructor
89
      def initialize
1✔
90
        @id = @@last_id += 1
1,092✔
91
        @ip_aliases = []
1,092✔
92
        # TODO: maybe do test query if physical interface is attached to proposal?
93
        @bootproto = BootProtocol::STATIC
1,092✔
94
        @ip = IPConfig.new(IPAddress.from_string("0.0.0.0/32"))
1,092✔
95
        @startmode = Startmode.create("manual")
1,092✔
96
        @ethtool_options = ""
1,092✔
97
        @firewall_zone = ""
1,092✔
98
        @hostnames = []
1,092✔
99
      end
100

101
      eql_attr :name, :interface, :bootproto, :ip, :ip_aliases, :mtu, :startmode, :description,
1✔
102
        :lladdress, :ethtool_options, :firewall_zone, :hostname
103

104
      PROPOSED_PPPOE_MTU = 1492 # suggested value for PPPoE
1✔
105

106
      # Propose reasonable defaults for given config. Useful for newly created devices.
107
      # @note difference between constructor and propose is that initialize should set simple
108
      #   defaults and propose have more tricky config that depends on env, product, etc.
109
      def propose
1✔
110
        propose_startmode
645✔
111
        self.mtu = PROPOSED_PPPOE_MTU if Yast::Arch.s390 && type.lcs?
645✔
112
      end
113

114
      def propose_startmode
1✔
115
        Yast.import "ProductFeatures"
645✔
116

117
        if root_filesystem_in_network?
645✔
118
          log.info "startmode nfsroot"
11✔
119
          @startmode = Startmode.create("nfsroot")
11✔
120
          return
11✔
121
        end
122

123
        product_startmode = Yast::ProductFeatures.GetStringFeature(
634✔
124
          "network",
125
          "startmode"
126
        )
127

128
        startmode = case product_startmode
634✔
129
        when "ifplugd"
UNCOV
130
          if replace_ifplugd?
×
UNCOV
131
            hotplug_interface? ? "hotplug" : "auto"
×
132
          else
133
            product_startmode
×
134
          end
135
        when "auto"
136
          "auto"
607✔
137
        else
138
          hotplug_interface? ? "hotplug" : "auto"
27✔
139
        end
140

141
        @startmode = Startmode.create(startmode)
634✔
142
      end
143

144
      # Returns the connection type
145
      #
146
      # Any subclass could define this method is the default
147
      # logic does not match.
148
      #
149
      # @return [InterfaceType] Interface type
150
      def type
1✔
151
        const_name = self.class.name.split("::").last.upcase
353✔
152
        InterfaceType.const_get(const_name)
353✔
153
      end
154

155
      # Whether a connection needs a virtual device associated or not.
156
      #
157
      # @return [Boolean]
158
      def virtual?
1✔
159
        false
31✔
160
      end
161

162
      # Returns all IP configurations
163
      #
164
      # @return [Array<IPConfig>]
165
      def all_ips
1✔
166
        ([ip] + ip_aliases).compact
8✔
167
      end
168

169
      # find parent from given collection of configs
170
      # @param configs [ConnectionConfigsCollection]
171
      # @return [ConnectionConfig::Bonding, ConnectionConfig::Bridge, nil] gets bridge, bonding or
172
      # nil in which this device in included
173
      def find_parent(configs)
1✔
174
        configs.find do |config|
54✔
175
          # TODO: what about VLAN?
176
          if config.type.bonding?
88✔
177
            config.ports.include?(name)
2✔
178
          elsif config.type.bridge?
86✔
179
            config.ports.include?(name)
27✔
180
          end
181
        end
182
      end
183

184
      # Return whether the connection is configured using the dhcp protocol or not
185
      #
186
      # @return [Boolean] true when using dhcp; false otherwise
187
      def dhcp?
1✔
188
        bootproto ? bootproto.dhcp? : false
16✔
189
      end
190

191
      # Return whether the connection is configured using a fixed IPADDR
192
      #
193
      # @return [Boolean] true when static protocol is used or not defined
194
      #   bootpro; false otherwise
195
      def static?
1✔
196
        bootproto ? bootproto.static? : true
42✔
197
      end
198

199
      # Convenience method to check whether a connection is configured using
200
      # the static bootproto and a valid IP address.
201
      #
202
      # @return [Boolean] whether the connection is configured with a valid
203
      #   static IP address or not
204
      def static_valid_ip?
1✔
205
        return false unless bootproto.static?
46✔
206

207
        ip && ip.address.to_s != "0.0.0.0"
26✔
208
      end
209

210
      # Return the first hostname associated with the primary IP address.
211
      #
212
      # @return [String, nil] returns the hostname associated with the primary
213
      #   IP address or nil
214
      def hostname
1✔
215
        hostnames&.first
178✔
216
      end
217

218
      # Convenience method in order to modify the canonical hostname mapped to
219
      # the primary IP address.
220
      #
221
      # @param hname [String, nil] hostnamme mapped to the primary IP address
222
      def hostname=(hname)
1✔
223
        short_name = hname&.split(".")&.first
16✔
224

225
        @hostnames = [hname, short_name].uniq.compact
16✔
226
        log.info("Assigned hostnames #{@hostnames.inspect} to connection #{name}")
16✔
227
      end
228

229
    private
1✔
230

231
      def replace_ifplugd?
1✔
UNCOV
232
        Yast.import "Arch"
×
233

UNCOV
234
        return true if !Yast::Arch.is_laptop
×
235
        # virtual devices cannot expect any event from ifplugd
236
        return true if virtual?
×
237

238
        false
×
239
      end
240

241
      def hotplug_interface?
1✔
242
        # virtual interface is not hotplugable
243
        return false if virtual?
27✔
244
        # if interface is not there
245
        return true unless interface
10✔
246

247
        false
×
248
        # TODO: interface is just string so interface.hardware.hotplug does not work
249
      end
250

251
      def root_filesystem_in_network?
1✔
252
        return false unless Yast::Mode.normal
645✔
253

254
        # see bsc#176804
255
        devicegraph = Y2Storage::StorageManager.instance.staging
634✔
256
        devicegraph.filesystem_in_network?("/")
634✔
257
      end
258
    end
259
  end
260
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc