[From nobody Fri Oct 25 12:00:15 2013 From: openlmiproject@gmail.com Precedence: list MIME-Version: 1.0 To: openlmi-reviews@lists.fedorahosted.org Date: Thu, 24 Oct 2013 15:25:34 +0200 Reply-To: openlmi-reviews@lists.fedorahosted.org Message-ID: <52691fd1.46df0e0a.5241.ffffefeb@mx.google.com> Content-Type: multipart/mixed; boundary="===============0373627642183752322==" Subject: buildbot failure in OpenLMI on networking-rawhide Message: 2 --===============0373627642183752322== MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit The Buildbot has detected a failed build on builder networking-rawhide while building OpenLMI. Full details are available at: http://openlmi-rnovacek.rhcloud.com/builders/networking-rawhide/builds/110 Buildbot URL: http://openlmi-rnovacek.rhcloud.com/ Buildslave for this Build: rawhide-slave Build Reason: 'try' job Build Source Stamp: [branch master] 343c310fde4ad9ff7c9f893350d615180090c8ba (plus patch) Blamelist: BUILD FAILED: failed tests selinux check sincerely, -The Buildbot --===============0373627642183752322== MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="source patch 0" diff --git a/doc/admin/concepts.rst b/doc/admin/concepts.rst new file mode 100644 index 0000000..e80b5b1 --- /dev/null +++ b/doc/admin/concepts.rst @@ -0,0 +1,157 @@ +.. _concepts: + +Networking API concepts +======================= + +OpenLMI-Networking provides CIM API. Some CIM knowledge is required and this +guide assumes that reader can routinely read and modify remote CIM objects +and call their intrinsic and extrinsic methods. + +Hardware representation +----------------------- + +.. _hardware: + +There is instance of subclass of :ref:`CIM_NetworkPort<CIM-NetworkPort>` +for each physical network device present in the system, e.g. +:ref:`LMI_EthernetPort<LMI-EthernetPort>` for ethernet ports. + +Instances of class :ref:`LMI_LANEndpoint <LMI-LANEndpoint>` represent +communication endpoints, identified by MAC address to which the network port +will respond. It's associated to the corresponding instance of +:ref:`CIM_NetworkPort<CIM-NetworkPort>` subclass via instance of +:ref:`LMI_NetworkDeviceSAPImplementation<LMI-NetworkDeviceSAPImplementation>`. + +.. figure:: pic/intro-hardware.svg + +Current network configuration +----------------------------- + +:ref:`LMI_IPNetworkConnection<LMI-IPNetworkConnection>` instances +represents the network connection in the system, e.g. "eth0", "p1p1". +Instances of this class are associated to the +:ref:`LMI_LANEndpoint<LMI-LANEndpoint>` via +:ref:`LMI_EndpointForIPNetworkConnection<LMI-EndpointForIPNetworkConnection>`. + +.. note:: + There are usually 1:1:1 relation between instances of CIM_NetworkPort + subclasses, LMI_LANEndpoint instances and LMI_IPNetworkConnection + instance in this provider. The classes are implemented for sake of + compatibility with DMTF profiles. + +:ref:`LMI_IPProtocolEndpoint<LMI-IPProtocolEndpoint>` - there is instance +of this class for each IP address on any network device and the instance is +associated with :ref:`LMI_IPNetworkConnection<LMI-IPNetworkConnection>` via +:ref:`LMI_NetworkSAPSAPDependency<LMI-NetworkSAPSAPDependency>` and with +:ref:`LMI_LANEndpoint<LMI-LANEndpoint>` via +:ref:`LMI_BindsToLANEndpoint<LMI-BindsToLANEndpoint>`. + +Default gateway is represented by instance of +:ref:`LMI_NetworkRemoteServiceAccessPoint <LMI-NetworkRemoteServiceAccessPoint>` +with attribute ``AccessContext`` equal to ``2 (Default Gateway)``. + +Instances of class :ref:`LMI_IPVersionSettingData <LMI-IPVersionSettingData>` +represent IPv4 or IPv6 support. If there is instance of this class associated +with :ref:`CIM_ComputerSystem <CIM-ComputerSystem>` it means that the system +supports IPv4 and/or IPv6 (depending on value of the ProtocolIFType property). +Instances of this class can be associated also to +:ref:`LMI_IPNetworkConnection <LMI-IPNetworkConnection>`. +It means that the network connection supports IPv4 and/or IPv6. + +.. figure:: pic/intro-current.svg + +Settings +-------- + +The OpenLMI networking provider is based on concept of ``setting``. +``Setting`` is a set of configuration options that can be applied +to an interface. Each setting is represented by instance of +:ref:`LMI_IPAssignmentSettingData <LMI-IPAssignmentSettingData>` +and it is aggregator for detailed configuration represented by instances +of following classes: :ref:`LMI_DHCPSettingData <LMI-DHCPSettingData>`, +:ref:`LMI_DNSSettingData <LMI-DNSSettingData>`, +:ref:`LMI_ExtendedStaticIPAssignmentSettingData <LMI-ExtendedStaticIPAssignmentSettingData>`. +These detailed settings are associated with the master setting via +:ref:`LMI_OrderedIPAssignmentComponent <LMI-OrderedIPAssignmentComponent>` +where the master has role ``GroupComponent``. + +``Settings`` available for given port are associated by +:ref:`LMI_IPElementSettingData <LMI-IPElementSettingData>`. +Its property ``IsCurrent`` is ``1`` when the setting is currently active. +Property ``IsDefault`` is ``1`` when the setting is automatically activated. + +.. figure:: pic/intro-setting.svg + +Altering and applying settings +------------------------------ + +Method +:ref:`LMI_CreateIPSetting<LMI-IPNetworkConnectionCapabilities-LMI-CreateIPSetting>` +of the :ref:`LMI_IPNetworkConnectionCapabilites <LMI-IPNetworkConnectionCapabilities>` +class can be used to create new setting. The setting will be tied to +:ref:`LMI_IPNetworkConnection <LMI-IPNetworkConnection>` that is associated +with given +:ref:`LMI_IPNetworkConnectionCapabilites<LMI-IPNetworkConnectionCapabilities>`. + +Singleton class :ref:`LMI_IPConfigurationService<LMI-IPConfigurationService>` +provides method +:ref:`ApplySettingToIPNetworkConnection<LMI-IPConfigurationService-ApplySettingToIPNetworkConnection>` +that applies :ref:`LMI_IPAssignmentSettingData<LMI-IPAssignmentSettingData>` +to :ref:`LMI_IPNetworkConnection<LMI-IPNetworkConnection>`. + +Bridging and bonding +-------------------- + +Current state +^^^^^^^^^^^^^ + +Instance of the :ref:`LMI_LinkAggregator8023ad<LMI-LinkAggregator8023ad>` +class represents currently active bond. It's associated to the +:ref:`LMI_LAGPort8023ad<LMI-LAGPort8023ad>` representing bonded interface via +:ref:`LMI_LinkAggregationBindsTo<LMI-LinkAggregationBindsTo>`. + +Instance of the :ref:`LMI_SwitchService<LMI-SwitchService>` class represents +currently active bridge. It's associated to the +:ref:`LMI_SwitchPort<LMI-SwitchPort>` representing bridged interface via +:ref:`LMI_SwitchesAmong<LMI-SwitchesAmong>`". + + +Creating bridge/bond +^^^^^^^^^^^^^^^^^^^^ + +Creating bridge/bond setting is the same as creating any other setting, just +the ``Type`` parameter of the +:ref:`LMI_CreateIPSetting<LMI-IPNetworkConnectionCapabilities-LMI-CreateIPSetting>` +is different (``Bonding`` or ``Bridging``). + +Bonding/bridging setting details can be altered by changing the properties of +:ref:`LMI_BondingMasterSettingData<LMI-BondingMasterSettingData>` (or +:ref:`LMI_BridgingMasterSettingData<LMI-BridgingMasterSettingData>`) instance +that is returned from the +:ref:`LMI_CreateIPSetting<LMI-IPNetworkConnectionCapabilities-LMI-CreateIPSetting>` +method. + +For activating bridge/bond setting, use +:ref:`ApplySettingToIPNetworkConnection<LMI-IPConfigurationService-ApplySettingToIPNetworkConnection>` +of the :ref:`LMI_IPConfigurationService<LMI-IPConfigurationService>` class. + +For deletion of the bridge/bond setting just delete the "master" setting +(the one created by +:ref:`LMI_CreateIPSetting<LMI-IPNetworkConnectionCapabilities-LMI-CreateIPSetting>`). +Deleting other settings will just remove the slave from the settings. + +Enslaving +^^^^^^^^^ + +First network interface is enslaved to the given bond/bridge setting +automatically (depending on what +:ref:`LMI_IPNetworkConnectionCapabilities<LMI-IPNetworkConnectionCapabilities>` +is the +:ref:`LMI_CreateIPSetting<LMI-IPNetworkConnectionCapabilities-LMI-CreateIPSetting>` +method called). Other interface can be enslaved by using +:ref:`LMI_CreateSlaveSetting<LMI-IPNetworkConnectionCapabilities-LMI-CreateSlaveSetting>` +method of the :ref:`LMI_IPNetworkConnectionCapabilities<LMI-IPNetworkConnectionCapabilities>`. + +Alter the :ref:`LMI_BondingSlaveSettingData<LMI-BondingSlaveSettingData>` (or +:ref:`LMI_BridgingSlaveSettingData<LMI-BridgingSlaveSettingData>`) instance to +change the properties of bond/bridge slave. diff --git a/doc/admin/index.rst b/doc/admin/index.rst index b2cf3a0..873c1c5 100644 --- a/doc/admin/index.rst +++ b/doc/admin/index.rst @@ -8,12 +8,18 @@ This provider is based on following `DMTF <http://dmtf.org>`_ standards: * `DSP1116 - IP Configuration Profile <http://dmtf.org/sites/default/files/standards/documents/DSP1116_1.0.0.pdf>`_ * `DSP1035 - Host LAN Network Port Profile <http://dmtf.org/sites/default/files/standards/documents/DSP1035_1.0.2.pdf>`_ +The knowledge of these standards is not necessary, but it can help a lot. + +Application developers should first get familliar with :ref:`Networking API concepts <concepts>` +and then look at :ref:`usage of OpenLMI-Networking <usage>`. + Content: .. toctree:: :maxdepth: 2 - usage-generic + concepts + usage .. ifconfig:: includeClasses diff --git a/doc/admin/usage-generic.rst b/doc/admin/usage-generic.rst deleted file mode 100644 index b28cecb..0000000 --- a/doc/admin/usage-generic.rst +++ /dev/null @@ -1,43 +0,0 @@ -Networking API concepts -======================= - -Hardware representation ------------------------ - -There is instance of subclass of :ref:`CIM_NetworkPort <CIM-NetworkPort>` for each physical network device present in the system, e.g. :ref:`LMI_EthernetPort <LMI-EthernetPort>` for ethernet ports. - -Instances of class :ref:`LMI_LANEndpoint <LMI-LANEndpoint>` represent communication endpoints, identified by MAC address to which the network port will respond. It's associated to the corresponding instance of :ref:`CIM_NetworkPort <CIM-NetworkPort>` subclass via instance of :ref:`LMI_NetworkDeviceSAPImplementation <LMI-NetworkDeviceSAPImplementation>`. - -.. figure:: pic/intro-hardware.svg - -Current network configuration ------------------------------ - -:ref:`LMI_IPNetworkConnection <LMI-IPNetworkConnection>` instances are representation of the network connection in the system, e.g. "eth0", "p1p1". Instance of this class is associated to :ref:`LMI_LANEndpoint <LMI-LANEndpoint>` via instance of :ref:`LMI_EndpointForIPNetworkConnection <LMI-EndpointForIPNetworkConnection>`. - -.. note:: - There are usually 1:1:1 relation between instances of CIM_NetworkPort subclasses, LMI_LANEndpoint instances and LMI_IPNetworkConnection instance in this provider. The classes are implemented for sake of compatibility with DMTF profiles. - -:ref:`LMI_IPProtocolEndpoint <LMI-IPProtocolEndpoint>` - there is instance of this class for each IP address on any network device and the instance is associated with :ref:`LMI_IPNetworkConnection <LMI-IPNetworkConnection>` via :ref:`LMI_NetworkSAPSAPDependency <LMI-NetworkSAPSAPDependency>` and with :ref:`LMI_LANEndpoint <LMI-LANEndpoint>` via :ref:`LMI_BindsToLANEndpoint <LMI-BindsToLANEndpoint>`. - -Default gateway is represented by instance of :ref:`LMI_NetworkRemoteServiceAccessPoint <LMI-NetworkRemoteServiceAccessPoint>` with attribute ``AccessContext`` equal to ``2 (Default Gateway)``. - -Instances of class :ref:`LMI_IPVersionSettingData <LMI-IPVersionSettingData>` represent IPv4 or IPv6 support. If there is instance of this class associated with :ref:`CIM_ComputerSystem <CIM-ComputerSystem>` it means that the system supports IPv4 and/or IPv6 (depending on value of ProtocolIFType property). Instances of this class can be associated also to :ref:`LMI_IPNetworkConnection <LMI-IPNetworkConnection>`. It means that the network connection supports IPv4 and/or IPv6. - -.. figure:: pic/intro-current.svg - -Settings --------- - -The OpenLMI networking provider is based on concept of ``connections``. ``Connection`` is set of settings that can be applied to interface. Each connection is represented by instance of :ref:`LMI_IPAssignmentSettingData <LMI-IPAssignmentSettingData>` and it is aggregator for detailed settings represented by instances of following classes: :ref:`LMI_DHCPSettingData <LMI-DHCPSettingData>`, :ref:`LMI_DNSSettingData <LMI-DNSSettingData>`, :ref:`LMI_ExtendedStaticIPAssignmentSettingData <LMI-ExtendedStaticIPAssignmentSettingData>`. These detailed setting is associated with master setting via :ref:`LMI_OrderedIPAssignmentComponent <LMI-OrderedIPAssignmentComponent>` where the master has role ``GroupComponent``. - -``Connections`` available to port are associated by :ref:`LMI_IPElementSettingData <LMI-IPElementSettingData>`. Its property ``IsCurrent`` is ``1`` when the connection is currently active. Property ``IsDefault`` is ``1`` when the connection is automatically activated. - -.. figure:: pic/intro-setting.svg - -Altering and applying connections ---------------------------------- - -Method :ref:`LMI_CreateIPSetting <LMI-IPNetworkConnectionCapabilities-LMI-CreateIPSetting>` of :ref:`LMI_IPNetworkConnectionCapabilites <LMI-IPNetworkConnectionCapabilities>` can be used to create new ``connection``. The ``connection`` will be bonded to :ref:`LMI_IPNetworkConnection <LMI-IPNetworkConnection>` that is associated with given :ref:`LMI_IPNetworkConnectionCapabilites <LMI-IPNetworkConnectionCapabilities>`. - -Singleton class :ref:`LMI_IPConfigurationService <LMI-IPConfigurationService>` provides method :ref:`ApplySettingToIPNetworkConnection <LMI-IPConfigurationService-ApplySettingToIPNetworkConnection>` that applies :ref:`LMI_IPAssignmentSettingData <LMI-IPAssignmentSettingData>` to :ref:`LMI_IPNetworkConnection <LMI-IPNetworkConnection>`. diff --git a/doc/admin/usage.rst b/doc/admin/usage.rst new file mode 100755 index 0000000..7975bea --- /dev/null +++ b/doc/admin/usage.rst @@ -0,0 +1,343 @@ +.. _usage: + +OpenLMI-Networking usage +======================== + +All example scripts are for ``lmishell``. See it's documentation_ on OpenLMI_ +page. + +.. _documentation: https://fedorahosted.org/openlmi/wiki/shell +.. _OpenLMI: https://fedorahosted.org/openlmi/ + +We also assume that ``lmishell`` is connected to the CIMOM and the +connection is stored in ``connection`` variable and variable ``ns`` points to +cimv2 namespace:: + + connection = connect("server", "username", "password") + ns = connection.root.cimv2 + +Enumeration of network devices +------------------------------ + +Obtaining a list of network devices can be done by executing following +commands in ``lmishell``:: + + for device in ns.LMI_IPNetworkConnection.instances(): + print device.ElementName + + +Get parameters of network devices +--------------------------------- + +Obtaining parameters of network device might be a little bit tricky. +DMTF standards split network device to three classes and one might need +to traverse between them through associations, see +:ref:`Networking API concepts <hardware>`. + +Following example prints name, its status, MAC address, link technology and +maximal speed for each device. + +MAC address is not in the :ref:`LMI_IPNetworkConnection<LMI-IPNetworkConnection>` +class and must be accessed through +:ref:`LMI_EndpointForIPNetworkConnection<LMI-EndpointForIPNetworkConnection>` +association to :ref:`LMI_LANEndpoint<LMI-LANEndpoint>` class, +same for MaxSpeed and LinkTechnology, those are in +:ref:`CIM_NetworkPort<CIM-NetworkPort>` subclasses, associated through +:ref:`LMI_NetworkDeviceSAPImplementation<LMI-NetworkDeviceSAPImplementation>` +class:: + + for device in ns.LMI_IPNetworkConnection.instances(): + # print device name + print device.ElementName, + # print operating status + print ns.LMI_IPNetworkConnection.OperatingStatusValues.value_name(device.OperatingStatus), + + # MAC address in not part of LMI_IPNetworkConnection but LMI_LANEndpoint class, + # which is associated through LMI_EndpointForIPNetworkConnection + lanendpoint = device.first_associator(AssocClass="LMI_EndpointForIPNetworkConnection") + + # print MAC address + print lanendpoint.MACAddress, + + # LinkTechnology is part of CIM_NetworkPort subclasses, we need to traverse + # through LMI_NetworkDeviceSAPImplementation association + networkport = lanendpoint.first_associator(AssocClass="LMI_NetworkDeviceSAPImplementation") + + # print link technology + print ns.CIM_NetworkPort.LinkTechnologyValues.value_name(networkport.LinkTechnology), + + # network speed might not be defined + if networkport.MaxSpeed: + # Convert bps to Mbps + print "%dMbps" % (networkport.MaxSpeed // (1024*1024)), + else: + print "unknown", + print + + +Get current IP configuration +---------------------------- + +Current IP addresses are in the +:ref:`LMI_IPProtocolEndpoint<LMI-IPProtocolEndpoint>` class associated +to given :ref:`LMI_IPNetworkConnection<LMI-IPNetworkConnection>`:: + + device = ns.LMI_IPNetworkConnection.first_instance({'ElementName': 'eth0'}) + for endpoint in device.associators(AssocClass="LMI_NetworkSAPSAPDependency", ResultClass="LMI_IPProtocolEndpoint"): + if endpoint.ProtocolIFType == ns.LMI_IPProtocolEndpoint.ProtocolIFTypeValues.IPv4: + print "IPv4: %s/%s" % (endpoint.IPv4Address, endpoint.SubnetMask) + elif endpoint.ProtocolIFType == ns.LMI_IPProtocolEndpoint.ProtocolIFTypeValues.IPv6: + print "IPv6: %s/%d" % (endpoint.IPv6Address, endpoint.IPv6SubnetPrefixLength) + +Default gateway is represented by instance of +:ref:`LMI_NetworkRemoteServiceAccessPoint<LMI-NetworkRemoteServiceAccessPoint>` +with ``AccessContext`` equal to ``DefaultGateway``:: + + for rsap in device.associators(AssocClass="LMI_NetworkRemoteAccessAvailableToElement", ResultClass="LMI_NetworkRemoteServiceAccessPoint"): + if rsap.AccessContext == ns.LMI_NetworkRemoteServiceAccessPoint.AccessContextValues.DefaultGateway: + print "Default Gateway: %s" % rsap.AccessInfo + + +For the list of DNS servers we need to traverse the object model a little bit. +First get :ref:`LMI_IPProtocolEndpoint<LMI-IPProtocolEndpoint>` instances +associated with given :ref:`LMI_IPNetworkConnection<LMI-IPNetworkConnection>` +via :ref:`LMI_NetworkSAPSAPDependency<LMI-NetworkSAPSAPDependency>`. +Then use the same association to get instances of +:ref:`LMI_DNSProtocolEndpoint<LMI-DNSProtocolEndpoint>`. +Finally instances of +:ref:`LMI_NetworkRemoteServiceAccessPoint<LMI-NetworkRemoteServiceAccessPoint>` +with ``AccessContext`` equal to ``DNS Server`` associated through +:ref:`LMI_NetworkRemoteAccessAvailableToElement<LMI-NetworkRemoteAccessAvailableToElement>` +have the DNS server address in the ``AccessInfo`` property. + +Note that there might be more possible path to get to the +RemoteServiceAccessPath and you might get duplicated entries. The ``set`` is +used here to deduplicate the list of DNS servers:: + + dnsservers = set() + for ipendpoint in device.associators(AssocClass="LMI_NetworkSAPSAPDependency", ResultClass="LMI_IPProtocolEndpoint"): + for dnsedpoint in ipendpoint.associators(AssocClass="LMI_NetworkSAPSAPDependency", ResultClass="LMI_DNSProtocolEndpoint"): + for rsap in dnsedpoint.associators(AssocClass="LMI_NetworkRemoteAccessAvailableToElement", ResultClass="LMI_NetworkRemoteServiceAccessPoint"): + if rsap.AccessContext == ns.LMI_NetworkRemoteServiceAccessPoint.AccessContextValues.DNSServer: + dnsservers.add(rsap.AccessInfo) + print "DNS:", ", ".join(dnsservers) + + +Bring up / take down a network device +------------------------------------- + +.. note:: + Changing the state of a network device is not recommended! Just disconnect + the active setting. + +Use method :ref:`RequestStateChange<LMI-LANEndpoint-RequestStateChange>` of the +:ref:`LMI_LANEndpoint<LMI-LANEndpoint>` object. ``RequestedState`` parameter +can be either ``Enabled`` or ``Disabled``:: + + lanendpoint = ns.LMI_LANEndpoint.first_instance({ "ElementName": "eth0" }) + lanendpoint.RequestStateChange(RequestedState=ns.LMI_LANEndpoint.RequestedStateValues.Enabled) + + +Enumerate available settings +---------------------------- + +One setting is a set of configuration options that are applicable to a network +interface. This setting is represented by a +:ref:`LMI_IPAssignmentSettingData<LMI-IPAssignmentSettingData>` instances that +have ``AddressOrigin`` equal to ``Cumulative Configuration``:: + + for settingdata in ns.LMI_IPAssignmentSettingData.instances(): + if settingdata.AddressOrigin == ns.LMI_IPAssignmentSettingData.AddressOriginValues.cumulativeconfiguration: + print "Setting: %s" % settingdata.Caption + +Obtaining setting details +------------------------- + +Setting configuration is spread between the instances of +:ref:`LMI_IPAssignmentSettingData<LMI-IPAssignmentSettingData>` subclasses +associated with the "master" setting:: + + settingdata = ns.LMI_IPAssignmentSettingData.first_instance({ "Caption": "eth0" }) + for setting in settingdata.associators(AssocClass="LMI_OrderedIPAssignmentComponent"): + if setting.classname == "LMI_DHCPSettingData": + if setting.ProtocolIFType == ns.LMI_IPAssignmentSettingData.ProtocolIFTypeValues.IPv4: + print "IPv4 DHCP" + else: + print "IPv6 DHCPv6" + elif setting.classname == "LMI_ExtendedStaticIPAssignmentSettingData": + for i in range(len(setting["IPAddresses"])): + if setting["ProtocolIFType"] == ns.LMI_IPAssignmentSettingData.ProtocolIFTypeValues.IPv4: + print "Static IPv4 address: %s/%s, Gateway %s" % ( + setting["IPAddresses"][i], + setting["SubnetMasks"][i], + setting["GatewayAddresses"][i]) + else: + print "Static IPv6 address: %s/%d, Gateway %s" % ( + setting["IPAddresses"][i], + setting["IPv6SubnetPrefixLengths"][i], + setting["GatewayAddresses"][i]) + elif (setting.classname == "LMI_IPAssignmentSettingData" and + setting["AddressOrigin"] == ns.LMI_IPAssignmentSettingData.AddressOriginValues.Stateless): + print "IPv6 Stateless" + +Create new setting +------------------ + +New setting is created by calling +:ref:`LMI_CreateIPSetting<LMI-IPNetworkConnectionCapabilities-LMI-CreateIPSetting>` +method on the instance of +:ref:`LMI_IPNetworkConnectionCapabilities<LMI-IPNetworkConnectionCapabilities>`, +which is associated with :ref:`LMI_IPNetworkConnection<LMI-IPNetworkConnection>` +through +:ref:`LMI_IPNetworkConnectionElementCapabilities<LMI-IPNetworkConnectionElementCapabilities>`. +It also has the ``ElementName`` property same as is the name of the network +interface. + +Created setting can be modified by using ``ModifyInstance`` intrinsic method +(``push()`` in the lmishell). + +Let's say we want to create a new setting with static IPv4 and stateless IPv6 +configuration for given network interface:: + + capability = ns.LMI_IPNetworkConnectionCapabilities.first_instance({ 'ElementName': 'eth0' }) + result = capability.LMI_CreateIPSetting(Caption='eth0 Static', + IPv4Type=capability.LMI_CreateIPSetting.IPv4TypeValues.Static, + IPv6Type=capability.LMI_CreateIPSetting.IPv6TypeValues.Stateless) + setting = result.rparams["SettingData"].to_instance() + for settingData in setting.associators(AssocClass="LMI_OrderedIPAssignmentComponent"): + if setting.ProtocolIFType == ns.LMI_IPAssignmentSettingData.ProtocolIFTypeValues.IPv4: + # Set static IPv4 address + settingData.IPAddresses = ["192.168.1.100"] + settingData.SubnetMasks = ["255.255.0.0"] + settingData.GatewayAddresses = ["192.168.1.1"] + settingData.push() + + +Set DNS servers for given setting +--------------------------------- + +DNS server for given setting is stored in the +:ref:`DNSServerAddresses<LMI-DNSSettingData-DNSServerAddresses>` property +of class :ref:`LMI_DNSSettingData<LMI-DNSSettingData>`. + +Following code adds IPv4 DNS server to the existing setting:: + + setting = ns.LMI_IPAssignmentSettingData.first_instance({ "Caption": "eth0 Static" }) + for settingData in setting.associators(AssocClass="LMI_OrderedIPAssignmentComponent"): + if (settingData.classname == "LMI_DNSSettingData" and + settingData.ProtocolIFType == ns.LMI_IPAssignmentSettingData.ProtocolIFTypeValues.IPv4): + settingData.DNSServerAddresses.append("192.168.1.1") + settingData.push() + +Manage static routes for given setting +-------------------------------------- + +Static route can be added by calling +:ref:`LMI_AddStaticIPRoute<LMI-IPAssignmentSettingData-LMI-AddStaticIPRoute>` +method on the instance of the +:ref:`LMI_IPAssignmentSettingData<LMI-IPAssignmentSettingData>` class:: + + setting = ns.LMI_IPAssignmentSettingData.first_instance({ "Caption": "eth0 Static" }) + result = setting.LMI_AddStaticIPRoute( + AddressType=setting.LMI_AddStaticIPRouteValues.IPv4, + DestinationAddress="192.168.2.1", + DestinationMask="255.255.255.0") + route = result.rparams["Route"] + +Additional parameters can be set by modifying the instance of +:ref:`LMI_IPRouteSettingData<LMI-IPRouteSettingData>`. The route can be deleted +by using ``DeleteInstance`` intrinsic method (``delete()`` in lmishell). + +Delete setting +-------------- + +For setting deletion just call DeleteInstance intrinsic method (``delete()`` +in the lmishell) to the instance of +:ref:`LMI_IPAssignmentSettingData<LMI-IPAssignmentSettingData>`:: + + setting = ns.LMI_IPAssignmentSettingData.first_instance({ 'Caption': 'eth0 Static' }) + setting.delete() + +Apply setting +------------- + +The setting can by applied to the network interface by calling +:ref:`ApplySettingToIPNetworkConnection<LMI-IPConfigurationService-ApplySettingToIPNetworkConnection>` +of the :ref:`LMI_IPConfigurationService<LMI-IPConfigurationService>` class. + +This method is asynchronous and returns a job, but lmishell can call it +synchronously:: + + setting = ns.LMI_IPAssignmentSettingData.first_instance({ "Caption": "eth0 Static" }) + port = ns.LMI_IPNetworkConnection.first_instance({ 'ElementName': 'ens8' }) + service = ns.LMI_IPConfigurationService.first_instance() + service.SyncApplySettingToIPNetworkConnection(SettingData=setting, IPNetworkConnection=port, Mode=32768) + +``Mode`` parameter affects how is the setting applied. Most commonly used +values are: + +* Mode 1 -- apply the setting now and make it auto-activated +* Mode 2 -- just make it auto-activated, don't apply now +* Mode 4 -- disconnect and disable auto-activation +* Mode 5 -- don't change the setting state, only disable auto-activation +* Mode 32768 -- apply the setting +* Mode 32769 -- disconnect + + +Bridging and bonding +-------------------- + +Setting up +^^^^^^^^^^ + +Use following code to create and activate bond with eth0 and eth1 interfaces:: + + # Get the interfaces + interface1 = ns.LMI_IPNetworkConnection.first_instance({ 'ElementName': 'eth0' }) + interface2 = ns.LMI_IPNetworkConnection.first_instance({ 'ElementName': 'eth1' }) + + # Get the capabilities + capability1 = interface1.first_associator(AssocClass="LMI_IPNetworkConnectionElementCapabilities", + ResultClass="LMI_IPNetworkConnectionCapabilities") + capability2 = interface2.first_associator(AssocClass="LMI_IPNetworkConnectionElementCapabilities", + ResultClass="LMI_IPNetworkConnectionCapabilities") + # Use one of the capabilities to create the bond + result = capability1.LMI_CreateIPSetting(Caption='Bond', + Type=capability1.LMI_CreateIPSetting.TypeValues.Bonding, + IPv4Type=capability1.LMI_CreateIPSetting.IPv4TypeValues.DHCP) + setting = result.rparams["SettingData"].to_instance() + # Enslave the second interface using the second capability + capability2.LMI_CreateSlaveSetting(MasterSettingData=setting) + service = ns.LMI_IPConfigurationService.first_instance() + # Activate the bond + service.SyncApplySettingToIPNetworkConnection( + SettingData=setting, + IPNetworkConnection=interface1, + Mode=32768) + service.SyncApplySettingToIPNetworkConnection( + SettingData=setting, + IPNetworkConnection=interface2, + Mode=32768) + +Displaying current state +^^^^^^^^^^^^^^^^^^^^^^^^ + +Following code displays existing bonds and bonded interfaces:: + + for linkaggregation in ns.LMI_LinkAggregator8023ad.instances(): + print "Bond: %s" % linkaggregation.Name + for lagport in linkaggregation.associators(AssocClass="LMI_LinkAggregationBindsTo", + ResultClass="LMI_LAGPort8023ad"): + print "Bonded interface: %s" % lagport.Name + +Following code displays existing bridges and bridged interfaces:: + + for switchservice in ns.LMI_SwitchService.instances(): + print "Bridge: %s" % switchservice.Name + for switchport in switchservice.associators(AssocClass="LMI_SwitchesAmong", + ResultClass="LMI_SwitchPort"): + print "Bridged interface: %s" % switchport.Name + +.. todo:: + Document notifications about changes in network devices and settings + (created, modified, deleted) diff --git a/src/LMI_IPNetworkConnectionCapabilitiesProvider.c b/src/LMI_IPNetworkConnectionCapabilitiesProvider.c index 1252b3d..cf738ba 100644 --- a/src/LMI_IPNetworkConnectionCapabilitiesProvider.c +++ b/src/LMI_IPNetworkConnectionCapabilitiesProvider.c @@ -217,7 +217,7 @@ static int get_device_id(Network *network, const char *prefix) for (size_t i = 0; i < ports_length(ports); ++i) { name = port_get_id(ports_index(ports, i)); if (strncmp(name, prefix, len) == 0) { - id = atoi(name + 4); + id = atoi(name + len); if (id > max) { max = id; } diff --git a/src/LMI_OrderedIPAssignmentComponentProvider.c b/src/LMI_OrderedIPAssignmentComponentProvider.c index 44d9149..7fe8bcc 100644 --- a/src/LMI_OrderedIPAssignmentComponentProvider.c +++ b/src/LMI_OrderedIPAssignmentComponentProvider.c @@ -73,9 +73,8 @@ static CMPIStatus LMI_OrderedIPAssignmentComponentEnumInstances( size_t j, k; Setting *setting; - Connection *connection, *slave; + Connection *connection, *slave, *master; char *instanceid, *name, *classname; - const char *master_id; network_lock(network); const Connections *connections = network_get_connections(network); if (connections == NULL) { @@ -105,8 +104,9 @@ static CMPIStatus LMI_OrderedIPAssignmentComponentEnumInstances( // Find if there are slave connections for this connection for (j = 0; j < connections_length(connections); ++j) { slave = connections_index(connections, j); - master_id = connection_get_master_connection_id(slave); - if (master_id != NULL && strcmp(master_id, connection_get_id(connection)) == 0) { + master = connection_get_master_connection(slave); + if (master != NULL && connection_get_id(master) != NULL && + strcmp(connection_get_id(master), connection_get_id(connection)) == 0) { LMI_OrderedIPAssignmentComponent w; LMI_OrderedIPAssignmentComponent_Init(&w, _cb, ns); diff --git a/src/connection.c b/src/connection.c index 5fc91de..64529ef 100644 --- a/src/connection.c +++ b/src/connection.c @@ -206,12 +206,41 @@ LMIResult connection_set_port(Connection *connection, Port *port) LMIResult connection_set_master_connection(Connection *connection, const Connection *master, SettingType type) { - return connection_priv_set_master_connection(connection, master, type); + if ((connection->master_id = strdup(master->id)) == NULL) { + error("Memory allocation failed"); + return LMI_ERROR_MEMORY; + } + if (type == SETTING_TYPE_BOND) { + if ((connection->slave_type = strdup("bond")) == NULL) { + error("Memory allocation failed"); + return LMI_ERROR_MEMORY; + } + } + if (type == SETTING_TYPE_BRIDGE) { + if ((connection->slave_type = strdup("bridge")) == NULL) { + error("Memory allocation failed"); + return LMI_ERROR_MEMORY; + } + } + return LMI_SUCCESS; } -const char *connection_get_master_connection_id(Connection *connection) +Connection *connection_get_master_connection(Connection *connection) { - return connection->master_id; + if (connection->master_id == NULL) { + return NULL; + } + const Connections *connections = connection->network->connections; + Connection *c; + for (size_t i = 0; i < connections_length(connections); ++i) { + c = connections_index(connections, i); + if ((strcmp(connection->master_id, c->id)) == 0 || + (strcmp(connection->master_id, c->name) == 0)) { + + return c; + } + } + return NULL; } bool connection_compare(const Connection *c1, const Connection *c2) diff --git a/src/connection.h b/src/connection.h index f3d0369..537febc 100644 --- a/src/connection.h +++ b/src/connection.h @@ -147,10 +147,10 @@ LMIResult connection_set_master_connection(Connection *connection, const Connect * Gets master connection for given slave connection * * \param connection slave connection - * \retval id master connection id - * \retval NULL if connection is not slave + * \return \p Connection master connection or NULL if the slave doesn't + * have master connection */ -const char *connection_get_master_connection_id(Connection *connection); +Connection *connection_get_master_connection(Connection *connection); /** * Add new setting to the list of the settings. diff --git a/src/connection_nm.c b/src/connection_nm.c index 8d3d37b..c4f9a0a 100644 --- a/src/connection_nm.c +++ b/src/connection_nm.c @@ -321,9 +321,13 @@ GHashTable *connection_to_hash(Connection *connection, LMIResult *res) goto err; } if (connection->port != NULL) { + const char *mac = connection->port->permmac; + if (mac == NULL) { + mac = connection->port->mac; + } if ((*res = g_hash_table_insert_boxed(subhash, "mac-address", DBUS_TYPE_G_UCHAR_ARRAY, - macToGByteArray(connection->port->mac), true)) != LMI_SUCCESS) { + macToGByteArray(mac), true)) != LMI_SUCCESS) { goto err; } @@ -381,27 +385,6 @@ void connection_priv_free(void *priv) free(p); } -LMIResult connection_priv_set_master_connection(Connection *connection, const Connection *master, SettingType type) -{ - if ((connection->master_id = strdup(master->id)) == NULL) { - error("Memory allocation failed"); - return LMI_ERROR_MEMORY; - } - if (type == SETTING_TYPE_BOND) { - if ((connection->slave_type = strdup("bond")) == NULL) { - error("Memory allocation failed"); - return LMI_ERROR_MEMORY; - } - } - if (type == SETTING_TYPE_BRIDGE) { - if ((connection->slave_type = strdup("bridge")) == NULL) { - error("Memory allocation failed"); - return LMI_ERROR_MEMORY; - } - } - return LMI_SUCCESS; -} - LMIResult connection_get_properties(Connection *connection) { ConnectionPriv *priv = connection->priv; diff --git a/src/connection_private.h b/src/connection_private.h index c387c53..2855da3 100644 --- a/src/connection_private.h +++ b/src/connection_private.h @@ -46,7 +46,4 @@ LMIResult connection_priv_delete(const Connection *connection); void *connection_priv_new(void); void connection_priv_free(void *priv); -LMIResult connection_priv_set_master_connection(Connection *connection, const Connection *master, SettingType type); -Connection *connection_priv_get_master_connection(Connection *connection); - #endif diff --git a/src/ipassignmentsettingdata.c b/src/ipassignmentsettingdata.c index c4a2ef8..f3b2f3d 100644 --- a/src/ipassignmentsettingdata.c +++ b/src/ipassignmentsettingdata.c @@ -480,6 +480,7 @@ CMPIStatus IPAssignmentSettingDataEnumInstances( const Connections *connections = network_get_connections(network); for (size_t i = 0; i < connections_length(connections); ++i) { connection = connections_index(connections, i); + Connection *master = connection_get_master_connection(connection); if (connection_get_type(connection) == CONNECTION_TYPE_BOND && type == LMI_BondingMasterSettingData_Type) { @@ -522,8 +523,7 @@ CMPIStatus IPAssignmentSettingDataEnumInstances( CMSetStatus(&res, CMPI_RC_ERR_FAILED); break; } - } else if (connection_get_master_connection_id(connection) != NULL) { - Connection *master = connections_find_by_id(connections, connection_get_master_connection_id(connection)); + } else if (master != NULL) { // This is slave connection if (type == LMI_BridgingSlaveSettingData_Type && connection_get_type(master) == CONNECTION_TYPE_BRIDGE) { @@ -712,11 +712,13 @@ CMPIStatus IPAssignmentSettingDataDeleteInstance( CMReturn(CMPI_RC_ERR_FAILED); } // Delete all slave connections first - const char *master_id; + Connection *master; for (size_t i = 0; i < connections_length(connections); ++i) { c = connections_index(connections, i); - master_id = connection_get_master_connection_id(c); - if (master_id != NULL && strcmp(master_id, uuid) == 0) { + master = connection_get_master_connection(c); + if (master != NULL && connection_get_id(master) != NULL && + strcmp(connection_get_id(master), uuid) == 0) { + if ((res = network_delete_connection(network, c)) != LMI_SUCCESS) { break; } diff --git a/src/network.c b/src/network.c index c9246da..c0e45c1 100644 --- a/src/network.c +++ b/src/network.c @@ -219,14 +219,13 @@ LMIResult network_activate_connection(Network *network, const Port *port, const if (type == CONNECTION_TYPE_BOND || type == CONNECTION_TYPE_BRIDGE) { // Activate slave connection const Connections *connections = network_get_connections(network); - Connection *c; - const char *master_id; + Connection *c, *master; // Find slave connection with given port for (size_t i = 0; i < connections_length(connections); ++i) { c = connections_index(connections, i); - master_id = connection_get_master_connection_id(c); - if (master_id != NULL && - strcmp(master_id, connection->id) == 0 && + master = connection_get_master_connection(c); + if (master != NULL && connection_get_id(master) != NULL && + strcmp(connection_get_id(master), connection->id) == 0 && port_compare(connection_get_port(c), port)) { return network_priv_activate_connection(network, port, c, job); diff --git a/src/setting.c b/src/setting.c index 37e5033..77760c3 100644 --- a/src/setting.c +++ b/src/setting.c @@ -70,7 +70,15 @@ Setting *setting_new(SettingType setting_type) setting->typespec.bond.arp_ip_target = NULL; break; case SETTING_TYPE_BRIDGE: + // Default values as specified by NetworkManager + // see man nm-settings(5) setting->typespec.bridge.interface_name = NULL; + setting->typespec.bridge.stp = true; + setting->typespec.bridge.priority = 128; + setting->typespec.bridge.forward_delay = 15; + setting->typespec.bridge.hello_time = 2; + setting->typespec.bridge.max_age = 20; + setting->typespec.bridge.ageing_time = 500; break; case SETTING_TYPE_BRIDGE_SLAVE: // Default values as specified by NetworkManager diff --git a/test/run_tests.py b/test/run_tests.py index d7517bb..9a3e82a 100755 --- a/test/run_tests.py +++ b/test/run_tests.py @@ -124,7 +124,8 @@ if __name__ == '__main__': options.tests = [] print "------ nosetests" - nose = IOThread("/usr/bin/nosetests", ["-v", "--process-timeout=20"] + options.tests, env=os.environ, cwd=os.path.dirname(__file__), timeout=60) + nose = IOThread("/usr/bin/nosetests", ["-v", "--process-timeout=20"] + options.tests, + env=os.environ, cwd=os.path.dirname(os.path.abspath(__file__)), timeout=60) nose.start() if fake_cimom is not None: fake_cimom.run_debugger() --===============0373627642183752322==-- ]