~harlowja/cloud-init/cloud-init-net-sysconfig

« back to all changes in this revision

Viewing changes to cloudinit/net/network_state.py

  • Committer: Joshua Harlow
  • Date: 2016-06-13 20:10:07 UTC
  • Revision ID: harlowja@gmail.com-20160613201007-hbiso1uectg3rw6g
Refactor some of sysconfig changes -> network_state module

Show diffs side-by-side

added added

removed removed

Lines of Context:
38
38
    """
39
39
    state = None
40
40
    if 'version' in net_config and 'config' in net_config:
41
 
        ns = NetworkState(version=net_config.get('version'),
42
 
                          config=net_config.get('config'))
43
 
        ns.parse_config(skip_broken=skip_broken)
44
 
        state = ns.network_state
 
41
        nsi = NetworkStateInterpreter(version=net_config.get('version'),
 
42
                                      config=net_config.get('config'))
 
43
        nsi.parse_config(skip_broken=skip_broken)
 
44
        state = nsi.network_state
45
45
    return state
46
46
 
47
47
 
57
57
 
58
58
 
59
59
def from_state_file(state_file):
60
 
    network_state = None
61
60
    state = util.read_conf(state_file)
62
 
    network_state = NetworkState()
63
 
    network_state.load(state)
64
 
    return network_state
 
61
    nsi = NetworkStateInterpreter()
 
62
    nsi.load(state)
 
63
    return nsi
65
64
 
66
65
 
67
66
def diff_keys(expected, actual):
113
112
                                                      parents, dct)
114
113
 
115
114
 
 
115
class NetworkState(object):
 
116
 
 
117
    def __init__(self, network_state, version=NETWORK_STATE_VERSION):
 
118
        self._network_state = copy.deepcopy(network_state)
 
119
        self._version = version
 
120
 
 
121
    @property
 
122
    def version(self):
 
123
        return self._version
 
124
 
 
125
    def iter_routes(self, filter_func=None):
 
126
        for route in self._network_state.get('routes', []):
 
127
            if filter_func is not None:
 
128
                if filter_func(route):
 
129
                    yield route
 
130
            else:
 
131
                yield route
 
132
 
 
133
    @property
 
134
    def dns_nameservers(self):
 
135
        try:
 
136
            return self._network_state['dns']['nameservers']
 
137
        except KeyError:
 
138
            return []
 
139
 
 
140
    @property
 
141
    def dns_searchdomains(self):
 
142
        try:
 
143
            return self._network_state['dns']['search']
 
144
        except KeyError:
 
145
            return []
 
146
 
 
147
    def iter_interfaces(self, filter_func=None):
 
148
        ifaces = self._network_state.get('interfaces', {})
 
149
        for iface in six.itervalues(ifaces):
 
150
            if filter_func is None:
 
151
                yield iface
 
152
            else:
 
153
                if filter_func(iface):
 
154
                    yield iface
 
155
 
 
156
 
116
157
@six.add_metaclass(CommandHandlerMeta)
117
 
class NetworkState(object):
 
158
class NetworkStateInterpreter(object):
118
159
 
119
160
    initial_network_state = {
120
161
        'interfaces': {},
126
167
    }
127
168
 
128
169
    def __init__(self, version=NETWORK_STATE_VERSION, config=None):
129
 
        self.version = version
130
 
        self.config = config
131
 
        self.network_state = copy.deepcopy(self.initial_network_state)
 
170
        self._version = version
 
171
        self._config = config
 
172
        self._network_state = copy.deepcopy(self.initial_network_state)
 
173
 
 
174
    @property
 
175
    def network_state(self):
 
176
        return NetworkState(self._network_state, version=self._version)
132
177
 
133
178
    def dump(self):
134
179
        state = {
135
 
            'version': self.version,
136
 
            'config': self.config,
137
 
            'network_state': self.network_state,
 
180
            'version': self._version,
 
181
            'config': self._config,
 
182
            'network_state': self._network_state,
138
183
        }
139
184
        return util.yaml_dumps(state)
140
185
 
141
186
    def load(self, state):
142
187
        if 'version' not in state:
143
188
            LOG.error('Invalid state, missing version field')
144
 
            raise Exception('Invalid state, missing version field')
 
189
            raise ValueError('Invalid state, missing version field')
145
190
 
146
191
        required_keys = NETWORK_STATE_REQUIRED_KEYS[state['version']]
147
192
        missing_keys = diff_keys(required_keys, state)
155
200
            setattr(self, key, state[key])
156
201
 
157
202
    def dump_network_state(self):
158
 
        return util.yaml_dumps(self.network_state)
 
203
        return util.yaml_dumps(self._network_state)
159
204
 
160
205
    def parse_config(self, skip_broken=True):
161
206
        # rebuild network state
162
 
        for command in self.config:
 
207
        for command in self._config:
163
208
            command_type = command['type']
164
209
            try:
165
210
                handler = self.command_handlers[command_type]
189
234
        }
190
235
        '''
191
236
 
192
 
        interfaces = self.network_state.get('interfaces')
 
237
        interfaces = self._network_state.get('interfaces', {})
193
238
        iface = interfaces.get(command['name'], {})
194
239
        for param, val in command.get('params', {}).items():
195
240
            iface.update({param: val})
215
260
            'gateway': None,
216
261
            'subnets': subnets,
217
262
        })
218
 
        self.network_state['interfaces'].update({command.get('name'): iface})
 
263
        self._network_state['interfaces'].update({command.get('name'): iface})
219
264
        self.dump_network_state()
220
265
 
221
266
    @ensure_command_keys(['name', 'vlan_id', 'vlan_link'])
228
273
                    hwaddress ether BC:76:4E:06:96:B3
229
274
                    vlan-raw-device eth0
230
275
        '''
231
 
        interfaces = self.network_state.get('interfaces')
 
276
        interfaces = self._network_state.get('interfaces', {})
232
277
        self.handle_physical(command)
233
278
        iface = interfaces.get(command.get('name'), {})
234
279
        iface['vlan-raw-device'] = command.get('vlan_link')
263
308
        '''
264
309
 
265
310
        self.handle_physical(command)
266
 
        interfaces = self.network_state.get('interfaces')
 
311
        interfaces = self._network_state.get('interfaces')
267
312
        iface = interfaces.get(command.get('name'), {})
268
313
        for param, val in command.get('params').items():
269
314
            iface.update({param: val})
270
315
        iface.update({'bond-slaves': 'none'})
271
 
        self.network_state['interfaces'].update({iface['name']: iface})
 
316
        self._network_state['interfaces'].update({iface['name']: iface})
272
317
 
273
318
        # handle bond slaves
274
319
        for ifname in command.get('bond_interfaces'):
280
325
                # inject placeholder
281
326
                self.handle_physical(cmd)
282
327
 
283
 
            interfaces = self.network_state.get('interfaces')
 
328
            interfaces = self._network_state.get('interfaces', {})
284
329
            bond_if = interfaces.get(ifname)
285
330
            bond_if['bond-master'] = command.get('name')
286
331
            # copy in bond config into slave
287
332
            for param, val in command.get('params').items():
288
333
                bond_if.update({param: val})
289
 
            self.network_state['interfaces'].update({ifname: bond_if})
 
334
            self._network_state['interfaces'].update({ifname: bond_if})
290
335
 
291
336
    @ensure_command_keys(['name', 'bridge_interfaces', 'params'])
292
337
    def handle_bridge(self, command):
319
364
 
320
365
        # find one of the bridge port ifaces to get mac_addr
321
366
        # handle bridge_slaves
322
 
        interfaces = self.network_state.get('interfaces')
 
367
        interfaces = self._network_state.get('interfaces', {})
323
368
        for ifname in command.get('bridge_interfaces'):
324
369
            if ifname in interfaces:
325
370
                continue
330
375
            # inject placeholder
331
376
            self.handle_physical(cmd)
332
377
 
333
 
        interfaces = self.network_state.get('interfaces')
 
378
        interfaces = self._network_state.get('interfaces', {})
334
379
        self.handle_physical(command)
335
380
        iface = interfaces.get(command.get('name'), {})
336
381
        iface['bridge_ports'] = command['bridge_interfaces']
341
386
 
342
387
    @ensure_command_keys(['address'])
343
388
    def handle_nameserver(self, command):
344
 
        dns = self.network_state.get('dns')
 
389
        dns = self._network_state.get('dns')
345
390
        if 'address' in command:
346
391
            addrs = command['address']
347
392
            if not type(addrs) == list:
357
402
 
358
403
    @ensure_command_keys(['destination'])
359
404
    def handle_route(self, command):
360
 
        routes = self.network_state.get('routes')
 
405
        routes = self._network_state.get('routes', [])
361
406
        network, cidr = command['destination'].split("/")
362
407
        netmask = cidr2mask(int(cidr))
363
408
        route = {