854bc07ee6ad1f8284b4a7c2268c88107c7ed97c
[csit.git] / resources / libraries / python / honeycomb / HcAPIKwInterfaces.py
1 # Copyright (c) 2016 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
5 #
6 #     http://www.apache.org/licenses/LICENSE-2.0
7 #
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13
14 """Keywords to manipulate interface configuration using Honeycomb REST API.
15
16 The keywords make possible to put and get configuration data and to get
17 operational data.
18 """
19
20 from resources.libraries.python.HTTPRequest import HTTPCodes
21 from resources.libraries.python.honeycomb.HoneycombSetup import HoneycombError
22 from resources.libraries.python.honeycomb.HoneycombUtil \
23     import DataRepresentation
24 from resources.libraries.python.honeycomb.HoneycombUtil \
25     import HoneycombUtil as HcUtil
26
27
28 class InterfaceKeywords(object):
29     """Keywords for Interface manipulation.
30
31     Implements keywords which get configuration and operational data about
32     vpp interfaces and set the interface's parameters using Honeycomb REST API.
33     """
34
35     INTF_PARAMS = ("name", "description", "type", "enabled",
36                    "link-up-down-trap-enable")
37     IPV4_PARAMS = ("enabled", "forwarding", "mtu")
38     IPV6_PARAMS = ("enabled", "forwarding", "mtu", "dup-addr-detect-transmits")
39     IPV6_AUTOCONF_PARAMS = ("create-global-addresses",
40                             "create-temporary-addresses",
41                             "temporary-valid-lifetime",
42                             "temporary-preferred-lifetime")
43     ETH_PARAMS = ("mtu", )
44     ROUTING_PARAMS = ("vrf-id", )
45     VXLAN_PARAMS = ("src", "dst", "vni", "encap-vrf-id")
46     L2_PARAMS = ("bridge-domain", "split-horizon-group",
47                  "bridged-virtual-interface")
48
49     def __init__(self):
50         pass
51
52     @staticmethod
53     def _configure_interface(node, interface, data,
54                              data_representation=DataRepresentation.JSON):
55         """Send interface configuration data and check the response.
56
57         :param node: Honeycomb node.
58         :param interface: The name of interface.
59         :param data: Configuration data to be sent in PUT request.
60         :param data_representation: How the data is represented.
61         :type node: dict
62         :type interface: str
63         :type data: dict
64         :type data_representation: DataRepresentation
65         :return: Content of response.
66         :rtype: bytearray
67         :raises HoneycombError: If the status code in response on PUT is not
68         200 = OK.
69         """
70
71         status_code, resp = HcUtil.\
72             put_honeycomb_data(node, "config_vpp_interfaces", data,
73                                data_representation=data_representation)
74         if status_code != HTTPCodes.OK:
75             raise HoneycombError(
76                 "The configuration of interface '{0}' was not successful. "
77                 "Status code: {1}.".format(interface, status_code))
78         return resp
79
80     @staticmethod
81     def get_all_interfaces_cfg_data(node):
82         """Get configuration data about all interfaces from Honeycomb.
83
84         :param node: Honeycomb node.
85         :type node: dict
86         :return: Configuration data about all interfaces from Honeycomb.
87         :rtype: list
88         :raises HoneycombError: If it is not possible to get configuration data.
89         """
90
91         status_code, resp = HcUtil.\
92             get_honeycomb_data(node, "config_vpp_interfaces")
93         if status_code != HTTPCodes.OK:
94             raise HoneycombError(
95                 "Not possible to get configuration information about the "
96                 "interfaces. Status code: {0}.".format(status_code))
97         try:
98             return resp["interfaces"]["interface"]
99
100         except (KeyError, TypeError):
101             return []
102
103     @staticmethod
104     def get_interface_cfg_data(node, interface):
105         """Get configuration data about the given interface from Honeycomb.
106
107         :param node: Honeycomb node.
108         :param interface: The name of interface.
109         :type node: dict
110         :type interface: str
111         :return: Configuration data about the given interface from Honeycomb.
112         :rtype: dict
113         """
114
115         intfs = InterfaceKeywords.get_all_interfaces_cfg_data(node)
116         for intf in intfs:
117             if intf["name"] == interface:
118                 return intf
119         return {}
120
121     @staticmethod
122     def get_all_interfaces_oper_data(node):
123         """Get operational data about all interfaces from Honeycomb.
124
125         :param node: Honeycomb node.
126         :type node: dict
127         :return: Operational data about all interfaces from Honeycomb.
128         :rtype: list
129         :raises HoneycombError: If it is not possible to get operational data.
130         """
131
132         status_code, resp = HcUtil.\
133             get_honeycomb_data(node, "oper_vpp_interfaces")
134         if status_code != HTTPCodes.OK:
135             raise HoneycombError(
136                 "Not possible to get operational information about the "
137                 "interfaces. Status code: {0}.".format(status_code))
138         try:
139             return resp["interfaces-state"]["interface"]
140
141         except (KeyError, TypeError):
142             return []
143
144     @staticmethod
145     def get_interface_oper_data(node, interface):
146         """Get operational data about the given interface from Honeycomb.
147
148         :param node: Honeycomb node.
149         :param interface: The name of interface.
150         :type node: dict
151         :type interface: str
152         :return: Operational data about the given interface from Honeycomb.
153         :rtype: dict
154         """
155
156         intfs = InterfaceKeywords.get_all_interfaces_oper_data(node)
157         for intf in intfs:
158             if intf["name"] == interface:
159                 return intf
160         return {}
161
162     @staticmethod
163     def _set_interface_properties(node, interface, path, new_value=None):
164         """Set interface properties.
165
166         This method reads interface configuration data, creates, changes or
167         removes the requested data and puts it back to Honeycomb.
168
169         :param node: Honeycomb node.
170         :param interface: The name of interface.
171         :param path:  Path to data we want to change / create / remove.
172         :param new_value: The new value to be set. If None, the item will be
173         removed.
174         :type node: dict
175         :type interface: str
176         :type path: tuple
177         :type new_value: str, dict or list
178         :return: Content of response.
179         :rtype: bytearray
180         :raises HoneycombError: If it is not possible to get or set the data.
181         """
182
183         status_code, resp = HcUtil.\
184             get_honeycomb_data(node, "config_vpp_interfaces")
185         if status_code != HTTPCodes.OK:
186             raise HoneycombError(
187                 "Not possible to get configuration information about the "
188                 "interfaces. Status code: {0}.".format(status_code))
189
190         if new_value:
191             new_data = HcUtil.set_item_value(resp, path, new_value)
192         else:
193             new_data = HcUtil.remove_item(resp, path)
194         return InterfaceKeywords._configure_interface(node, interface, new_data)
195
196     @staticmethod
197     def set_interface_state(node, interface, state="up"):
198         """Set VPP interface state.
199
200         The keyword changes the administration state of interface to up or down
201         depending on the parameter "state".
202
203         :param node: Honeycomb node.
204         :param interface: The name of interface.
205         :param state: The requested state, only "up" and "down" are valid
206         values.
207         :type node: dict
208         :type interface: str
209         :type state: str
210         :return: Content of response.
211         :rtype: bytearray
212         :raises KeyError: If the argument "state" is nor "up" or "down".
213         :raises HoneycombError: If the interface is not present on the node.
214         """
215
216         intf_state = {"up": "true",
217                       "down": "false"}
218
219         path = ("interfaces", ("interface", "name", str(interface)), "enabled")
220         return InterfaceKeywords._set_interface_properties(
221             node, interface, path, intf_state[state.lower()])
222
223     @staticmethod
224     def set_interface_up(node, interface):
225         """Set the administration state of VPP interface to up.
226
227         :param node: Honeycomb node.
228         :param interface: The name of interface.
229         :type node: dict
230         :type interface: str
231         :return: Content of response
232         :rtype: bytearray
233         """
234
235         return InterfaceKeywords.set_interface_state(node, interface, "up")
236
237     @staticmethod
238     def set_interface_down(node, interface):
239         """Set the administration state of VPP interface to down.
240
241         :param node: Honeycomb node.
242         :param interface: The name of interface.
243         :type node: dict
244         :type interface: str
245         :return: Content of response.
246         :rtype: bytearray
247         """
248
249         return InterfaceKeywords.set_interface_state(node, interface, "down")
250
251     @staticmethod
252     def add_bridge_domain_to_interface(node, interface, bd_name,
253                                        split_horizon_group=None, bvi=None):
254         """Add a new bridge domain to an interface and set its parameters.
255
256         :param node: Honeycomb node.
257         :param interface: The name of interface.
258         :param bd_name: Bridge domain name.
259         :param split_horizon_group: Split-horizon group name.
260         :param bvi: The bridged virtual interface.
261         :type node: dict
262         :type interface: str
263         :type bd_name: str
264         :type split_horizon_group: str
265         :type bvi: str
266         :return: Content of response.
267         :rtype: bytearray
268         :raises HoneycombError: If the interface is not present on the node.
269         """
270
271         v3po_l2 = {"bridge-domain": str(bd_name)}
272         if split_horizon_group:
273             v3po_l2["split-horizon-group"] = str(split_horizon_group)
274         if bvi:
275             v3po_l2["bridged-virtual-interface"] = str(bvi)
276
277         path = ("interfaces", ("interface", "name", str(interface)), "v3po:l2")
278
279         return InterfaceKeywords._set_interface_properties(
280             node, interface, path, v3po_l2)
281
282     @staticmethod
283     def configure_interface_base(node, interface, param, value):
284         """Configure the base parameters of interface.
285
286         :param node: Honeycomb node.
287         :param interface: The name of interface.
288         :param param: Parameter to configure (set, change, remove)
289         :param value: The value of parameter. If None, the parameter will be
290         removed.
291         :type node: dict
292         :type interface: str
293         :type param: str
294         :type value: str
295         :return: Content of response.
296         :rtype: bytearray
297         :raises HoneycombError: If the parameter is not valid.
298         """
299
300         if param not in InterfaceKeywords.INTF_PARAMS:
301             raise HoneycombError("The parameter {0} is invalid.".format(param))
302
303         path = ("interfaces", ("interface", "name", interface), param)
304         return InterfaceKeywords._set_interface_properties(
305             node, interface, path, value)
306
307     @staticmethod
308     def configure_interface_ipv4(node, interface, param, value):
309         """Configure IPv4 parameters of interface
310
311         :param node: Honeycomb node.
312         :param interface: The name of interface.
313         :param param: Parameter to configure (set, change, remove)
314         :param value: The value of parameter. If None, the parameter will be
315         removed.
316         :type node: dict
317         :type interface: str
318         :type param: str
319         :type value: str
320         :return: Content of response.
321         :rtype: bytearray
322         :raises HoneycombError: If the parameter is not valid.
323         """
324
325         if param not in InterfaceKeywords.IPV4_PARAMS:
326             raise HoneycombError("The parameter {0} is invalid.".format(param))
327
328         path = ("interfaces", ("interface", "name", interface),
329                 "ietf-ip:ipv4", param)
330         return InterfaceKeywords._set_interface_properties(
331             node, interface, path, value)
332
333     @staticmethod
334     def add_first_ipv4_address(node, interface, ip_addr, network):
335         """Add the first IPv4 address.
336
337         If there are any other addresses configured, they will be removed.
338
339         :param node: Honeycomb node.
340         :param interface: The name of interface.
341         :param ip_addr: IPv4 address to be set.
342         :param network: Netmask or length of network prefix.
343         :type node: dict
344         :type interface: str
345         :type ip_addr: str
346         :type network: str or int
347         :return: Content of response.
348         :rtype: bytearray
349         """
350
351         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4")
352         if isinstance(network, basestring):
353             address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
354         elif isinstance(network, int) and (0 < network < 33):
355             address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
356         else:
357             raise HoneycombError("Value {0} is not a valid netmask or network "
358                                  "prefix length.".format(network))
359         return InterfaceKeywords._set_interface_properties(
360             node, interface, path, address)
361
362     @staticmethod
363     def add_ipv4_address(node, interface, ip_addr, network):
364         """Add IPv4 address.
365
366         :param node: Honeycomb node.
367         :param interface: The name of interface.
368         :param ip_addr: IPv4 address to be set.
369         :param network: Netmask or length of network prefix.
370         :type node: dict
371         :type interface: str
372         :type ip_addr: str
373         :type network: str or int
374         :return: Content of response.
375         :rtype: bytearray
376         """
377
378         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
379                 "address")
380         if isinstance(network, basestring):
381             address = {"address": [{"ip": ip_addr, "netmask": network}, ]}
382         elif isinstance(network, int) and (0 < network < 33):
383             address = {"address": [{"ip": ip_addr, "prefix-length": network}, ]}
384         else:
385             raise HoneycombError("Value {0} is not a valid netmask or network "
386                                  "prefix length.".format(network))
387         return InterfaceKeywords._set_interface_properties(
388             node, interface, path, address)
389
390     @staticmethod
391     def remove_all_ipv4_addresses(node, interface):
392         """Remove all IPv4 addresses from interface.
393
394         :param node: Honeycomb node.
395         :param interface: The name of interface.
396         :type node: dict
397         :type interface: str
398         :return: Content of response.
399         :rtype: bytearray
400         """
401
402         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
403                 "address")
404         return InterfaceKeywords._set_interface_properties(
405             node, interface, path, None)
406
407     @staticmethod
408     def add_first_ipv4_neighbor(node, interface, ip_addr, link_layer_address):
409         """Add the first IPv4 neighbour.
410
411         If there are any other neighbours configured, they will be removed.
412
413         :param node: Honeycomb node.
414         :param interface: The name of interface.
415         :param ip_addr: IPv4 address of neighbour to be set.
416         :param link_layer_address: Link layer address.
417         :type node: dict
418         :type interface: str
419         :type ip_addr: str
420         :type link_layer_address: str
421         :return: Content of response.
422         :rtype: bytearray
423         """
424
425         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4")
426         neighbor = {"neighbor": [{"ip": ip_addr,
427                                   "link-layer-address": link_layer_address}, ]}
428         return InterfaceKeywords._set_interface_properties(
429             node, interface, path, neighbor)
430
431     @staticmethod
432     def add_ipv4_neighbor(node, interface, ip_addr, link_layer_address):
433         """Add the IPv4 neighbour.
434
435         :param node: Honeycomb node.
436         :param interface: The name of interface.
437         :param ip_addr: IPv4 address of neighbour to be set.
438         :param link_layer_address: Link layer address.
439         :type node: dict
440         :type interface: str
441         :type ip_addr: str
442         :type link_layer_address: str
443         :return: Content of response.
444         :rtype: bytearray
445         """
446
447         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
448                 "neighbor")
449         neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
450         return InterfaceKeywords._set_interface_properties(
451             node, interface, path, neighbor)
452
453     @staticmethod
454     def remove_all_ipv4_neighbors(node, interface):
455         """Remove all IPv4 neighbours.
456
457         :param node: Honeycomb node.
458         :param interface: The name of interface.
459         :type node: dict
460         :type interface: str
461         :return: Content of response.
462         :rtype: bytearray
463         """
464
465         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv4",
466                 "neighbor")
467         return InterfaceKeywords._set_interface_properties(
468             node, interface, path, None)
469
470     @staticmethod
471     def configure_interface_ipv6(node, interface, param, value):
472         """Configure IPv6 parameters of interface
473
474         :param node: Honeycomb node.
475         :param interface: The name of interface.
476         :param param: Parameter to configure (set, change, remove)
477         :param value: The value of parameter. If None, the parameter will be
478         removed.
479         :type node: dict
480         :type interface: str
481         :type param: str
482         :type value: str
483         :return: Content of response.
484         :rtype: bytearray
485         :raises HoneycombError: If the parameter is not valid.
486         """
487
488         if param in InterfaceKeywords.IPV6_PARAMS:
489             path = ("interfaces", ("interface", "name", interface),
490                     "ietf-ip:ipv6", param)
491         elif param in InterfaceKeywords.IPV6_AUTOCONF_PARAMS:
492             path = ("interfaces", ("interface", "name", interface),
493                     "ietf-ip:ipv6", "autoconf", param)
494         else:
495             raise HoneycombError("The parameter {0} is invalid.".format(param))
496
497         return InterfaceKeywords._set_interface_properties(
498             node, interface, path, value)
499
500     @staticmethod
501     def add_first_ipv6_address(node, interface, ip_addr, prefix_len):
502         """Add the first IPv6 address.
503
504         If there are any other addresses configured, they will be removed.
505
506         :param node: Honeycomb node.
507         :param interface: The name of interface.
508         :param ip_addr: IPv6 address to be set.
509         :param prefix_len: Prefix length.
510         :type node: dict
511         :type interface: str
512         :type ip_addr: str
513         :type prefix_len: str
514         :return: Content of response.
515         :rtype: bytearray
516         """
517
518         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
519         address = {"address": [{"ip": ip_addr, "prefix-length": prefix_len}, ]}
520         return InterfaceKeywords._set_interface_properties(
521             node, interface, path, address)
522
523     @staticmethod
524     def add_ipv6_address(node, interface, ip_addr, prefix_len):
525         """Add IPv6 address.
526
527         :param node: Honeycomb node.
528         :param interface: The name of interface.
529         :param ip_addr: IPv6 address to be set.
530         :param prefix_len: Prefix length.
531         :type node: dict
532         :type interface: str
533         :type ip_addr: str
534         :type prefix_len: str
535         :return: Content of response.
536         :rtype: bytearray
537         """
538
539         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
540                 "address")
541         address = [{"ip": ip_addr, "prefix-length": prefix_len}, ]
542         return InterfaceKeywords._set_interface_properties(
543             node, interface, path, address)
544
545     @staticmethod
546     def remove_all_ipv6_addresses(node, interface):
547         """Remove all IPv6 addresses from interface.
548
549         :param node: Honeycomb node.
550         :param interface: The name of interface.
551         :type node: dict
552         :type interface: str
553         :return: Content of response.
554         :rtype: bytearray
555         """
556
557         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
558                 "address")
559         return InterfaceKeywords._set_interface_properties(
560             node, interface, path, None)
561
562     @staticmethod
563     def add_first_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
564         """Add the first IPv6 neighbour.
565
566         If there are any other neighbours configured, they will be removed.
567
568         :param node: Honeycomb node.
569         :param interface: The name of interface.
570         :param ip_addr: IPv6 address of neighbour to be set.
571         :param link_layer_address: Link layer address.
572         :type node: dict
573         :type interface: str
574         :type ip_addr: str
575         :type link_layer_address: str
576         :return: Content of response.
577         :rtype: bytearray
578         """
579
580         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6")
581         neighbor = {"neighbor": [{"ip": ip_addr,
582                                   "link-layer-address": link_layer_address}, ]}
583         return InterfaceKeywords._set_interface_properties(
584             node, interface, path, neighbor)
585
586     @staticmethod
587     def add_ipv6_neighbor(node, interface, ip_addr, link_layer_address):
588         """Add the IPv6 neighbour.
589
590         :param node: Honeycomb node.
591         :param interface: The name of interface.
592         :param ip_addr: IPv6 address of neighbour to be set.
593         :param link_layer_address: Link layer address.
594         :type node: dict
595         :type interface: str
596         :type ip_addr: str
597         :type link_layer_address: str
598         :return: Content of response.
599         :rtype: bytearray
600         """
601
602         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
603                 "neighbor")
604         neighbor = [{"ip": ip_addr, "link-layer-address": link_layer_address}, ]
605         return InterfaceKeywords._set_interface_properties(
606             node, interface, path, neighbor)
607
608     @staticmethod
609     def remove_all_ipv6_neighbors(node, interface):
610         """Remove all IPv6 neighbours.
611
612         :param node: Honeycomb node.
613         :param interface: The name of interface.
614         :type node: dict
615         :type interface: str
616         :return: Content of response.
617         :rtype: bytearray
618         """
619
620         path = ("interfaces", ("interface", "name", interface), "ietf-ip:ipv6",
621                 "neighbor")
622         return InterfaceKeywords._set_interface_properties(
623             node, interface, path, None)
624
625     @staticmethod
626     def configure_interface_ethernet(node, interface, param, value):
627         """Configure the ethernet parameters of interface.
628
629         :param node: Honeycomb node.
630         :param interface: The name of interface.
631         :param param: Parameter to configure (set, change, remove)
632         :param value: The value of parameter. If None, the parameter will be
633         removed.
634         :type node: dict
635         :type interface: str
636         :type param: str
637         :type value: str
638         :return: Content of response.
639         :rtype: bytearray
640         :raises HoneycombError: If the parameter is not valid.
641         """
642
643         if param not in InterfaceKeywords.ETH_PARAMS:
644             raise HoneycombError("The parameter {0} is invalid.".format(param))
645         path = ("interfaces", ("interface", "name", interface), "v3po:ethernet",
646                 param)
647         return InterfaceKeywords._set_interface_properties(
648             node, interface, path, value)
649
650     @staticmethod
651     def configure_interface_routing(node, interface, param, value):
652         """Configure the routing parameters of interface.
653
654         :param node: Honeycomb node.
655         :param interface: The name of interface.
656         :param param: Parameter to configure (set, change, remove)
657         :param value: The value of parameter. If None, the parameter will be
658         removed.
659         :type node: dict
660         :type interface: str
661         :type param: str
662         :type value: str
663         :return: Content of response.
664         :rtype: bytearray
665         :raises HoneycombError: If the parameter is not valid.
666         """
667
668         if param not in InterfaceKeywords.ROUTING_PARAMS:
669             raise HoneycombError("The parameter {0} is invalid.".format(param))
670
671         path = ("interfaces", ("interface", "name", interface), "v3po:routing",
672                 param)
673         return InterfaceKeywords._set_interface_properties(
674             node, interface, path, value)
675
676     @staticmethod
677     def configure_interface_vxlan(node, interface, **kwargs):
678         """Configure VxLAN on the interface.
679
680         The keyword configures VxLAN parameters on the given interface. The type
681         of interface must be set to "v3po:vxlan-tunnel".
682         The new VxLAN parameters overwrite the current configuration. If a
683         parameter in new configuration is missing, it is removed from VxLAN
684         configuration.
685         If the dictionary kwargs is empty, VxLAN configuration is removed.
686
687         :param node: Honeycomb node.
688         :param interface: The name of interface.
689         :param kwargs: Parameters and their values. The accepted parameters are
690         defined in InterfaceKeywords.VXLAN_PARAMS.
691         :type node: dict
692         :type interface: str
693         :type kwargs: dict
694         :return: Content of response.
695         :rtype: bytearray
696         :raises HoneycombError: If the parameter is not valid.
697         """
698
699         vx_lan_structure = dict()
700         for param, value in kwargs.items():
701             if param not in InterfaceKeywords.VXLAN_PARAMS:
702                 raise HoneycombError("The parameter {0} is invalid.".
703                                      format(param))
704             vx_lan_structure[param] = value
705
706         path = ("interfaces", ("interface", "name", interface), "v3po:vxlan")
707         return InterfaceKeywords._set_interface_properties(
708             node, interface, path, vx_lan_structure)
709
710     @staticmethod
711     def configure_interface_l2(node, interface, param, value):
712         """Configure the L2 parameters of interface.
713
714         :param node: Honeycomb node.
715         :param interface: The name of interface.
716         :param param: Parameter to configure (set, change, remove)
717         :param value: The value of parameter. If None, the parameter will be
718         removed.
719         :type node: dict
720         :type interface: str
721         :type param: str
722         :type value: str
723         :return: Content of response.
724         :rtype: bytearray
725         :raises HoneycombError: If the parameter is not valid.
726         """
727
728         if param not in InterfaceKeywords.L2_PARAMS:
729             raise HoneycombError("The parameter {0} is invalid.".format(param))
730         path = ("interfaces", ("interface", "name", interface), "v3po:l2",
731                 param)
732         return InterfaceKeywords._set_interface_properties(
733             node, interface, path, value)