Skip to content

Commit b681f96

Browse files
committed
Add support for DHCP
Signed-off-by: Eric Bischoff <ebischoff@suse.com>
1 parent 8b066be commit b681f96

File tree

5 files changed

+133
-71
lines changed

5 files changed

+133
-71
lines changed

doc/source/parameters.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,6 +1085,8 @@ guest_networks_list:
10851085
Network information list of guest. It has one dictionary that contain some of the below
10861086
keys for each interface. All the keys are optional\:
10871087
1088+
- ``method``: interface initialization method. The valid values are ``static`` and
1089+
``dhcp``. Default is ``static``.
10881090
- ``ip_addr``: the IP address of the interface, ``cidr`` is required if IP address
10891091
is set
10901092
- ``dns_addr``: DNS servers address list

doc/source/restapi.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -815,7 +815,9 @@ Create guest NIC
815815

816816
**POST /guests/{userid}/nic**
817817

818-
Create a virtual NIC on giving guest.
818+
Create a virtual NIC on given guest.
819+
The NIC is created in the z/VM system directory, but it is not configured
820+
at the guest OS level.
819821

820822
* Request:
821823

@@ -844,7 +846,9 @@ Create network interface
844846

845847
**POST /guests/{userid}/interface**
846848

847-
Create one or more network interfaces on giving guest.
849+
Create one or more network interfaces on given guest.
850+
The interfaces are created in the z/VM system directory, and configured after
851+
the guest is started.
848852

849853
* Request:
850854

zvmsdk/api.py

Lines changed: 52 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2145,7 +2145,8 @@ def guest_create_network_interface(self, userid, os_version,
21452145
:param list guest_networks: a list of network info for the guest.
21462146
It has one dictionary that contain some of the below keys for
21472147
each network, the format is:
2148-
{'ip_addr': (str) IP address or None,
2148+
{'method': (str) 'static', 'dhcp', or None,
2149+
'ip_addr': (str) IP address or None,
21492150
'dns_addr': (list) DNS addresses or None,
21502151
'gateway_addr': (str) gateway address or None,
21512152
'cidr': (str) CIDR format,
@@ -2169,7 +2170,11 @@ def guest_create_network_interface(self, userid, os_version,
21692170
'dns_addr': ['9.0.2.1', '9.0.3.1'],
21702171
'gateway_addr': '192.168.96.1',
21712172
'cidr': "192.168.96.0/24",
2172-
'nic_vdev': '1003}]
2173+
'nic_vdev': '1003'},
2174+
{'method': 'dhcp',
2175+
'nic_vdev': '1004',
2176+
'mac_addr': '02:00:00:ab:cd:ef'}
2177+
]
21732178
:param bool active: whether add a NIC on active guest system
21742179
:returns: guest_networks list, including nic_vdev for each network
21752180
:rtype: list
@@ -2198,44 +2203,56 @@ def guest_create_network_interface(self, userid, os_version,
21982203
"digit")
21992204
raise exception.SDKInvalidInputFormat(msg=errmsg)
22002205

2201-
if (('ip_addr' in network.keys()) and
2202-
(network['ip_addr'] is not None)):
2203-
ip_addr = network['ip_addr']
2204-
if not netaddr.valid_ipv4(ip_addr):
2205-
errmsg = ("API guest_create_network_interface: "
2206-
"Invalid management IP address, it should be "
2207-
"the value between 0.0.0.0 and 255.255.255.255")
2208-
raise exception.SDKInvalidInputFormat(msg=errmsg)
2206+
method = 'static'
2207+
if (('method' in network.keys()) and
2208+
(network['method'] is not None)):
2209+
method = network['method'].lower()
2210+
if method == 'static':
2211+
if (('ip_addr' in network.keys()) and
2212+
(network['ip_addr'] is not None)):
2213+
ip_addr = network['ip_addr']
2214+
if not netaddr.valid_ipv4(ip_addr):
2215+
errmsg = ("API guest_create_network_interface: "
2216+
"Invalid IP address, it should be a "
2217+
"value between 0.0.0.0 and 255.255.255.255")
2218+
raise exception.SDKInvalidInputFormat(msg=errmsg)
2219+
2220+
if (('dns_addr' in network.keys()) and
2221+
(network['dns_addr'] is not None)):
2222+
if not isinstance(network['dns_addr'], list):
2223+
raise exception.SDKInvalidInputTypes(
2224+
'guest_config_network',
2225+
str(list), str(type(network['dns_addr'])))
2226+
for dns in network['dns_addr']:
2227+
if not netaddr.valid_ipv4(dns):
2228+
errmsg = ("API guest_create_network_interface: "
2229+
"Invalid DNS IP address, it should be a "
2230+
"value between 0.0.0.0 and 255.255.255.255")
2231+
raise exception.SDKInvalidInputFormat(msg=errmsg)
22092232

2210-
if (('dns_addr' in network.keys()) and
2211-
(network['dns_addr'] is not None)):
2212-
if not isinstance(network['dns_addr'], list):
2213-
raise exception.SDKInvalidInputTypes(
2214-
'guest_config_network',
2215-
str(list), str(type(network['dns_addr'])))
2216-
for dns in network['dns_addr']:
2217-
if not netaddr.valid_ipv4(dns):
2233+
if (('gateway_addr' in network.keys()) and
2234+
(network['gateway_addr'] is not None)):
2235+
if not netaddr.valid_ipv4(
2236+
network['gateway_addr']):
22182237
errmsg = ("API guest_create_network_interface: "
2219-
"Invalid DNS IP address, it should be a "
2238+
"Invalid gateway IP address, it should be a "
22202239
"value between 0.0.0.0 and 255.255.255.255")
22212240
raise exception.SDKInvalidInputFormat(msg=errmsg)
22222241

2223-
if (('gateway_addr' in network.keys()) and
2224-
(network['gateway_addr'] is not None)):
2225-
if not netaddr.valid_ipv4(
2226-
network['gateway_addr']):
2227-
errmsg = ("API guest_create_network_interface: "
2228-
"Invalid gateway IP address, it should be "
2229-
"a value between 0.0.0.0 and 255.255.255.255")
2230-
raise exception.SDKInvalidInputFormat(msg=errmsg)
2231-
if (('cidr' in network.keys()) and
2232-
(network['cidr'] is not None)):
2233-
if not zvmutils.valid_cidr(network['cidr']):
2234-
errmsg = ("API guest_create_network_interface: "
2235-
"Invalid CIDR, format should be a.b.c.d/n, where "
2236-
"a.b.c.d is a IP address, and n is the value "
2237-
"between 0 and 32")
2238-
raise exception.SDKInvalidInputFormat(msg=errmsg)
2242+
if (('cidr' in network.keys()) and
2243+
(network['cidr'] is not None)):
2244+
if not zvmutils.valid_cidr(network['cidr']):
2245+
errmsg = ("API guest_create_network_interface: "
2246+
"Invalid CIDR, format should be a.b.c.d/n, where "
2247+
"a.b.c.d is a IP address, and n is a value "
2248+
"between 0 and 32")
2249+
raise exception.SDKInvalidInputFormat(msg=errmsg)
2250+
2251+
elif method != 'dhcp':
2252+
errmsg = ("API guest_create_network_interface: "
2253+
"Invalid initialization method, it should be either "
2254+
"static or dhcp")
2255+
raise exception.SDKInvalidInputFormat(msg=errmsg)
22392256

22402257
try:
22412258
if OSA is None:

zvmsdk/dist.py

Lines changed: 64 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ def create_network_configuration_files(self, file_path, guest_networks,
4949
:param list guest_networks: a list of network info for the guest.
5050
It has one dictionary that contain some of the below keys for
5151
each network, the format is:
52-
{'ip_addr': (str) IP address,
52+
{'method': (str) NIC initialization method,
53+
'ip_addr': (str) IP address,
5354
'dns_addr': (list) DNS addresses,
5455
'gateway_addr': (str) gateway address,
5556
'cidr': (str) CIDR format
@@ -65,7 +66,11 @@ def create_network_configuration_files(self, file_path, guest_networks,
6566
'dns_addr': ['9.0.2.1', '9.0.3.1'],
6667
'gateway_addr': '192.168.96.1',
6768
'cidr': "192.168.96.0/24",
68-
'nic_vdev': '1003}]
69+
'nic_vdev': '1003'},
70+
{'method': 'dhcp',
71+
'nic_vdev': '1004',
72+
'mac_addr': '02:00:00:ab:cd:ef'}
73+
]
6974
:returns cfg_files: the network interface configuration file name
7075
and file content
7176
cmd_strings: shell command, helps to enable the network
@@ -124,11 +129,16 @@ def create_network_configuration_files(self, file_path, guest_networks,
124129
return cfg_files, cmd_strings, clean_cmd, net_enable_cmd
125130

126131
def _generate_network_configuration(self, network, vdev, active=False):
132+
method = 'static'
127133
ip_v4 = dns_str = gateway_v4 = ''
128134
ip_cidr = netmask_v4 = broadcast_v4 = ''
129135
net_cmd = mtu = ''
130136
dns_v4 = []
131137

138+
if (('method' in network.keys()) and
139+
(network['method'] is not None)):
140+
method = network['method']
141+
132142
if (('ip_addr' in network.keys()) and
133143
(network['ip_addr'] is not None)):
134144
ip_v4 = network['ip_addr']
@@ -164,12 +174,12 @@ def _generate_network_configuration(self, network, vdev, active=False):
164174
subchannels += ',0.0.%s' % address_write.lower()
165175
subchannels += ',0.0.%s' % address_data.lower()
166176

167-
cfg_str = self._get_cfg_str(device, broadcast_v4, gateway_v4,
177+
cfg_str = self._get_cfg_str(device, method, broadcast_v4, gateway_v4,
168178
ip_v4, netmask_v4, address_read,
169179
subchannels, dns_v4, mtu)
170180
cmd_str = self._get_cmd_str(address_read, address_write,
171181
address_data)
172-
route_str = self._get_route_str(gateway_v4)
182+
route_str = self._get_route_str(method, gateway_v4)
173183
if active and ip_v4 != '':
174184
if ip_cidr != '':
175185
mask = ip_cidr.rpartition('/')[2]
@@ -220,7 +230,7 @@ def get_volume_detach_configuration_cmds(self, fcp_list, target_wwpns,
220230
pass
221231

222232
@abc.abstractmethod
223-
def _get_cfg_str(self, device, broadcast_v4, gateway_v4, ip_v4,
233+
def _get_cfg_str(self, device, method, broadcast_v4, gateway_v4, ip_v4,
224234
netmask_v4, address_read, subchannels):
225235
"""construct configuration file of network device."""
226236
pass
@@ -231,7 +241,7 @@ def _get_device_filename(self, vdev):
231241
pass
232242

233243
@abc.abstractmethod
234-
def _get_route_str(self, gateway_v4):
244+
def _get_route_str(self, method, gateway_v4):
235245
"""construct a router string."""
236246
pass
237247

@@ -333,14 +343,15 @@ class rhel(LinuxDist):
333343
def _get_network_file_path(self):
334344
return '/etc/sysconfig/network-scripts/'
335345

336-
def _get_cfg_str(self, device, broadcast_v4, gateway_v4, ip_v4,
346+
def _get_cfg_str(self, device, method, broadcast_v4, gateway_v4, ip_v4,
337347
netmask_v4, address_read, subchannels, dns_v4, mtu):
338348
cfg_str = 'DEVICE=\"' + device + '\"\n'
339-
cfg_str += 'BOOTPROTO=\"static\"\n'
340-
cfg_str += 'BROADCAST=\"' + broadcast_v4 + '\"\n'
341-
cfg_str += 'GATEWAY=\"' + gateway_v4 + '\"\n'
342-
cfg_str += 'IPADDR=\"' + ip_v4 + '\"\n'
343-
cfg_str += 'NETMASK=\"' + netmask_v4 + '\"\n'
349+
cfg_str += 'BOOTPROTO=\"' + method + '"\n'
350+
if method == 'static':
351+
cfg_str += 'BROADCAST=\"' + broadcast_v4 + '\"\n'
352+
cfg_str += 'GATEWAY=\"' + gateway_v4 + '\"\n'
353+
cfg_str += 'IPADDR=\"' + ip_v4 + '\"\n'
354+
cfg_str += 'NETMASK=\"' + netmask_v4 + '\"\n'
344355
cfg_str += 'NETTYPE=\"qeth\"\n'
345356
cfg_str += 'ONBOOT=\"yes\"\n'
346357
cfg_str += 'PORTNAME=\"PORT' + address_read + '\"\n'
@@ -354,7 +365,7 @@ def _get_cfg_str(self, device, broadcast_v4, gateway_v4, ip_v4,
354365
i += 1
355366
return cfg_str
356367

357-
def _get_route_str(self, gateway_v4):
368+
def _get_route_str(self, method, gateway_v4):
358369
return ''
359370

360371
def _get_cmd_str(self, address_read, address_write, address_data):
@@ -702,7 +713,7 @@ def _delete_vdev_info(self, vdev):
702713
def _enable_network_interface(self, device, ip, broadcast):
703714
pass
704715

705-
def _get_cfg_str(self, device, broadcast_v4, gateway_v4, ip_v4,
716+
def _get_cfg_str(self, device, method, broadcast_v4, gateway_v4, ip_v4,
706717
netmask_v4, address_read, subchannels):
707718
pass
708719

@@ -724,7 +735,7 @@ def _get_dns_filename(self):
724735
def _get_network_file_path(self):
725736
pass
726737

727-
def _get_route_str(self, gateway_v4):
738+
def _get_route_str(self, method, gateway_v4):
728739
pass
729740

730741
def _get_udev_configuration(self, device, dev_channel):
@@ -754,12 +765,13 @@ class sles(LinuxDist):
754765
def _get_network_file_path(self):
755766
return '/etc/sysconfig/network/'
756767

757-
def _get_cfg_str(self, device, broadcast_v4, gateway_v4, ip_v4,
768+
def _get_cfg_str(self, device, method, broadcast_v4, gateway_v4, ip_v4,
758769
netmask_v4, address_read, subchannels, dns_v4, mtu):
759-
cfg_str = "BOOTPROTO=\'static\'\n"
760-
cfg_str += "IPADDR=\'%s\'\n" % ip_v4
761-
cfg_str += "NETMASK=\'%s\'\n" % netmask_v4
762-
cfg_str += "BROADCAST=\'%s\'\n" % broadcast_v4
770+
cfg_str = "BOOTPROTO=\'%s\'\n" % method
771+
if method == 'static':
772+
cfg_str += "IPADDR=\'%s\'\n" % ip_v4
773+
cfg_str += "NETMASK=\'%s\'\n" % netmask_v4
774+
cfg_str += "BROADCAST=\'%s\'\n" % broadcast_v4
763775
cfg_str += "STARTMODE=\'onboot\'\n"
764776
cfg_str += ("NAME=\'OSA Express Network card (%s)\'\n" %
765777
address_read)
@@ -770,8 +782,10 @@ def _get_cfg_str(self, device, broadcast_v4, gateway_v4, ip_v4,
770782
self.dns_v4 = None
771783
return cfg_str
772784

773-
def _get_route_str(self, gateway_v4):
774-
route_str = 'default %s - -\n' % gateway_v4
785+
def _get_route_str(self, method, gateway_v4):
786+
route_str = ''
787+
if method == 'static':
788+
route_str = 'default %s - -\n' % gateway_v4
775789
return route_str
776790

777791
def _get_cmd_str(self, address_read, address_write, address_data):
@@ -1070,7 +1084,8 @@ def create_network_configuration_files(self, file_path, guest_networks,
10701084
:param list guest_networks: a list of network info for the guest.
10711085
It has one dictionary that contain some of the below keys for
10721086
each network, the format is:
1073-
{'ip_addr': (str) IP address,
1087+
{'method': (str) NIC initialization method,
1088+
'ip_addr': (str) IP address,
10741089
'dns_addr': (list) DNS addresses,
10751090
'gateway_addr': (str) gateway address,
10761091
'cidr': (str) CIDR format
@@ -1086,7 +1101,11 @@ def create_network_configuration_files(self, file_path, guest_networks,
10861101
'dns_addr': ['9.0.2.1', '9.0.3.1'],
10871102
'gateway_addr': '192.168.96.1',
10881103
'cidr': "192.168.96.0/24",
1089-
'nic_vdev': '1003}]
1104+
'nic_vdev': '1003'},
1105+
{'method': 'dhcp',
1106+
'nic_vdev': '1004',
1107+
'mac_addr': '02:00:00:ab:cd:ef'}
1108+
]
10901109
"""
10911110
cfg_files = []
10921111
cmd_strings = ''
@@ -1151,20 +1170,26 @@ def _delete_vdev_info(self, vdev):
11511170
def _get_network_file(self):
11521171
return '/etc/network/interfaces'
11531172

1154-
def _get_cfg_str(self, device, broadcast_v4, gateway_v4, ip_v4,
1173+
def _get_cfg_str(self, device, method, broadcast_v4, gateway_v4, ip_v4,
11551174
netmask_v4, mtu):
11561175
cfg_str = 'auto ' + device + '\n'
1157-
cfg_str += 'iface ' + device + ' inet static\n'
1158-
cfg_str += 'address ' + ip_v4 + '\n'
1159-
cfg_str += 'netmask ' + netmask_v4 + '\n'
1160-
cfg_str += 'broadcast ' + broadcast_v4 + '\n'
1161-
cfg_str += 'gateway ' + gateway_v4 + '\n'
1176+
cfg_str += 'iface ' + device + ' inet ' + method + '\n'
1177+
if method == 'static':
1178+
cfg_str += 'address ' + ip_v4 + '\n'
1179+
cfg_str += 'netmask ' + netmask_v4 + '\n'
1180+
cfg_str += 'broadcast ' + broadcast_v4 + '\n'
1181+
cfg_str += 'gateway ' + gateway_v4 + '\n'
11621182
cfg_str += 'mtu ' + mtu + '\n'
11631183
return cfg_str
11641184

11651185
def _generate_network_configuration(self, network, vdev):
1186+
method = 'static'
11661187
ip_v4 = dns_str = gateway_v4 = ''
11671188
netmask_v4 = broadcast_v4 = ''
1189+
if (('method' in network.keys()) and
1190+
(network['method'] is not None)):
1191+
method = network['method']
1192+
11681193
if (('ip_addr' in network.keys()) and
11691194
(network['ip_addr'] is not None)):
11701195
ip_v4 = network['ip_addr']
@@ -1192,12 +1217,12 @@ def _generate_network_configuration(self, network, vdev):
11921217
mtu = str(network['mtu'])
11931218

11941219
device = self._get_device_name(vdev)
1195-
cfg_str = self._get_cfg_str(device, broadcast_v4, gateway_v4,
1220+
cfg_str = self._get_cfg_str(device, method, broadcast_v4, gateway_v4,
11961221
ip_v4, netmask_v4, mtu)
11971222

11981223
return cfg_str, dns_str
11991224

1200-
def _get_route_str(self, gateway_v4):
1225+
def _get_route_str(self, method, gateway_v4):
12011226
return ''
12021227

12031228
def _get_cmd_str(self, address_read, address_write, address_data):
@@ -1372,7 +1397,8 @@ def create_network_configuration_files(self, file_path, guest_networks,
13721397
:param list guest_networks: a list of network info for the guest.
13731398
It has one dictionary that contain some of the below keys for
13741399
each network, the format is:
1375-
{'ip_addr': (str) IP address,
1400+
{'method': (str) NIC initialization method,
1401+
'ip_addr': (str) IP address,
13761402
'dns_addr': (list) DNS addresses,
13771403
'gateway_addr': (str) gateway address,
13781404
'cidr': (str) CIDR format
@@ -1388,7 +1414,11 @@ def create_network_configuration_files(self, file_path, guest_networks,
13881414
'dns_addr': ['9.0.2.1', '9.0.3.1'],
13891415
'gateway_addr': '192.168.96.1',
13901416
'cidr': "192.168.96.0/24",
1391-
'nic_vdev': '1003}]
1417+
'nic_vdev': '1003'},
1418+
{'method': 'dhcp'
1419+
'nic_vdev': '1004',
1420+
'mac_addr': '02:00:00:ab:cd:ef'}
1421+
]
13921422
"""
13931423
cfg_files = []
13941424
cmd_strings = ''

0 commit comments

Comments
 (0)